3
0

iplink.c 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  4. * Patrick McHardy <kaber@trash.net>
  5. *
  6. * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  7. */
  8. #include <net/if.h>
  9. /*#include <net/if_packet.h> - not needed? */
  10. #include <netpacket/packet.h>
  11. #include <netinet/if_ether.h>
  12. #include <linux/if_vlan.h>
  13. #if ENABLE_FEATURE_IP_LINK_CAN
  14. # include <linux/can/netlink.h>
  15. #endif
  16. #include "ip_common.h" /* #include "libbb.h" is inside */
  17. #include "rt_names.h"
  18. #include "utils.h"
  19. #undef ETH_P_8021AD
  20. #define ETH_P_8021AD 0x88A8
  21. #undef VLAN_FLAG_REORDER_HDR
  22. #define VLAN_FLAG_REORDER_HDR 0x1
  23. #undef VLAN_FLAG_GVRP
  24. #define VLAN_FLAG_GVRP 0x2
  25. #undef VLAN_FLAG_LOOSE_BINDING
  26. #define VLAN_FLAG_LOOSE_BINDING 0x4
  27. #undef VLAN_FLAG_MVRP
  28. #define VLAN_FLAG_MVRP 0x8
  29. #undef IFLA_VLAN_PROTOCOL
  30. #define IFLA_VLAN_PROTOCOL 5
  31. #ifndef NLMSG_TAIL
  32. #define NLMSG_TAIL(nmsg) \
  33. ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
  34. #endif
  35. #ifndef IFLA_LINKINFO
  36. # define IFLA_LINKINFO 18
  37. # define IFLA_INFO_KIND 1
  38. # define IFLA_INFO_DATA 2
  39. #endif
  40. #ifndef IFLA_VLAN_MAX
  41. # define IFLA_VLAN_ID 1
  42. # define IFLA_VLAN_FLAGS 2
  43. struct ifla_vlan_flags {
  44. uint32_t flags;
  45. uint32_t mask;
  46. };
  47. #endif
  48. #if ENABLE_FEATURE_IP_LINK_CAN
  49. # ifndef CAN_CTRLMODE_ONE_SHOT
  50. # define CAN_CTRLMODE_ONE_SHOT 0x08 /* One-Shot mode */
  51. # endif
  52. # ifndef CAN_CTRLMODE_BERR_REPORTING
  53. # define CAN_CTRLMODE_BERR_REPORTING 0x10 /* Bus-error reporting */
  54. # endif
  55. # ifndef CAN_CTRLMODE_FD
  56. # define CAN_CTRLMODE_FD 0x20 /* CAN FD mode */
  57. # endif
  58. # ifndef CAN_CTRLMODE_PRESUME_ACK
  59. # define CAN_CTRLMODE_PRESUME_ACK 0x40 /* Ignore missing CAN ACKs */
  60. # endif
  61. # ifndef CAN_CTRLMODE_FD_NON_ISO
  62. # define CAN_CTRLMODE_FD_NON_ISO 0x80 /* CAN FD in non-ISO mode */
  63. # endif
  64. # ifndef IFLA_CAN_TERMINATION
  65. # define IFLA_CAN_TERMINATION 11
  66. # endif
  67. #endif
  68. /* taken from linux/sockios.h */
  69. #define SIOCSIFNAME 0x8923 /* set interface name */
  70. #if 0
  71. # define dbg(...) bb_error_msg(__VA_ARGS__)
  72. #else
  73. # define dbg(...) ((void)0)
  74. #endif
  75. #define str_on_off "on\0""off\0"
  76. enum {
  77. PARM_on = 0,
  78. PARM_off
  79. };
  80. /* Exits on error */
  81. static int get_ctl_fd(void)
  82. {
  83. int fd;
  84. fd = socket(PF_INET, SOCK_DGRAM, 0);
  85. if (fd >= 0)
  86. return fd;
  87. fd = socket(PF_PACKET, SOCK_DGRAM, 0);
  88. if (fd >= 0)
  89. return fd;
  90. return xsocket(PF_INET6, SOCK_DGRAM, 0);
  91. }
  92. /* Exits on error */
  93. static void do_chflags(char *dev, uint32_t flags, uint32_t mask)
  94. {
  95. struct ifreq ifr;
  96. int fd;
  97. strncpy_IFNAMSIZ(ifr.ifr_name, dev);
  98. fd = get_ctl_fd();
  99. xioctl(fd, SIOCGIFFLAGS, &ifr);
  100. if ((ifr.ifr_flags ^ flags) & mask) {
  101. ifr.ifr_flags &= ~mask;
  102. ifr.ifr_flags |= mask & flags;
  103. xioctl(fd, SIOCSIFFLAGS, &ifr);
  104. }
  105. close(fd);
  106. }
  107. /* Exits on error */
  108. static void do_changename(char *dev, char *newdev)
  109. {
  110. struct ifreq ifr;
  111. int fd;
  112. strncpy_IFNAMSIZ(ifr.ifr_name, dev);
  113. strncpy_IFNAMSIZ(ifr.ifr_newname, newdev);
  114. fd = get_ctl_fd();
  115. xioctl(fd, SIOCSIFNAME, &ifr);
  116. close(fd);
  117. }
  118. /* Exits on error */
  119. static void set_qlen(char *dev, int qlen)
  120. {
  121. struct ifreq ifr;
  122. int s;
  123. s = get_ctl_fd();
  124. memset(&ifr, 0, sizeof(ifr));
  125. strncpy_IFNAMSIZ(ifr.ifr_name, dev);
  126. ifr.ifr_qlen = qlen;
  127. xioctl(s, SIOCSIFTXQLEN, &ifr);
  128. close(s);
  129. }
  130. /* Exits on error */
  131. static void set_mtu(char *dev, int mtu)
  132. {
  133. struct ifreq ifr;
  134. int s;
  135. s = get_ctl_fd();
  136. memset(&ifr, 0, sizeof(ifr));
  137. strncpy_IFNAMSIZ(ifr.ifr_name, dev);
  138. ifr.ifr_mtu = mtu;
  139. xioctl(s, SIOCSIFMTU, &ifr);
  140. close(s);
  141. }
  142. /* Exits on error */
  143. static void set_master(char *dev, int master)
  144. {
  145. struct rtnl_handle rth;
  146. struct {
  147. struct nlmsghdr n;
  148. struct ifinfomsg i;
  149. char buf[1024];
  150. } req;
  151. memset(&req, 0, sizeof(req));
  152. req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
  153. req.n.nlmsg_flags = NLM_F_REQUEST;
  154. req.n.nlmsg_type = RTM_NEWLINK;
  155. req.i.ifi_family = preferred_family;
  156. xrtnl_open(&rth);
  157. req.i.ifi_index = xll_name_to_index(dev);
  158. //printf("master %i for %i\n", master, req.i.ifi_index);
  159. addattr_l(&req.n, sizeof(req), IFLA_MASTER, &master, 4);
  160. if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
  161. xfunc_die();
  162. }
  163. /* Exits on error */
  164. static void set_netns(char *dev, int netns)
  165. {
  166. struct rtnl_handle rth;
  167. struct {
  168. struct nlmsghdr n;
  169. struct ifinfomsg i;
  170. char buf[1024];
  171. } req;
  172. memset(&req, 0, sizeof(req));
  173. req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
  174. req.n.nlmsg_flags = NLM_F_REQUEST;
  175. req.n.nlmsg_type = RTM_NEWLINK;
  176. req.i.ifi_family = preferred_family;
  177. xrtnl_open(&rth);
  178. req.i.ifi_index = xll_name_to_index(dev);
  179. //printf("netns %i for %i\n", netns, req.i.ifi_index);
  180. addattr_l(&req.n, sizeof(req), IFLA_NET_NS_PID, &netns, 4);
  181. if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
  182. xfunc_die();
  183. }
  184. /* Exits on error */
  185. static int get_address(char *dev, int *htype)
  186. {
  187. struct ifreq ifr;
  188. struct sockaddr_ll me;
  189. int s;
  190. s = xsocket(PF_PACKET, SOCK_DGRAM, 0);
  191. /*memset(&ifr, 0, sizeof(ifr)); - SIOCGIFINDEX does not need to clear all */
  192. strncpy_IFNAMSIZ(ifr.ifr_name, dev);
  193. xioctl(s, SIOCGIFINDEX, &ifr);
  194. memset(&me, 0, sizeof(me));
  195. me.sll_family = AF_PACKET;
  196. me.sll_ifindex = ifr.ifr_ifindex;
  197. me.sll_protocol = htons(ETH_P_LOOP);
  198. xbind(s, (struct sockaddr*)&me, sizeof(me));
  199. bb_getsockname(s, (struct sockaddr*)&me, sizeof(me));
  200. //never happens:
  201. //if (getsockname(s, (struct sockaddr*)&me, &alen) == -1)
  202. // bb_perror_msg_and_die("getsockname");
  203. close(s);
  204. *htype = me.sll_hatype;
  205. return me.sll_halen;
  206. }
  207. /* Exits on error */
  208. static void parse_address(char *dev, int hatype, int halen, char *lla, struct ifreq *ifr)
  209. {
  210. int alen;
  211. memset(ifr, 0, sizeof(*ifr));
  212. strncpy_IFNAMSIZ(ifr->ifr_name, dev);
  213. ifr->ifr_hwaddr.sa_family = hatype;
  214. alen = hatype == 1/*ARPHRD_ETHER*/ ? 14/*ETH_HLEN*/ : 19/*INFINIBAND_HLEN*/;
  215. alen = ll_addr_a2n((unsigned char *)(ifr->ifr_hwaddr.sa_data), alen, lla);
  216. if (alen < 0)
  217. exit_FAILURE();
  218. if (alen != halen) {
  219. bb_error_msg_and_die("wrong address (%s) length: expected %d bytes", lla, halen);
  220. }
  221. }
  222. /* Exits on error */
  223. static void set_address(struct ifreq *ifr, int brd)
  224. {
  225. int s;
  226. s = get_ctl_fd();
  227. if (brd)
  228. xioctl(s, SIOCSIFHWBROADCAST, ifr);
  229. else
  230. xioctl(s, SIOCSIFHWADDR, ifr);
  231. close(s);
  232. }
  233. static void die_must_be_on_off(const char *msg) NORETURN;
  234. static void die_must_be_on_off(const char *msg)
  235. {
  236. bb_error_msg_and_die("argument of \"%s\" must be \"on\" or \"off\"", msg);
  237. }
  238. #if ENABLE_FEATURE_IP_LINK_CAN
  239. static uint32_t get_float_1000(char *arg, const char *errmsg)
  240. {
  241. uint32_t ret;
  242. double d;
  243. char *ptr;
  244. errno = 0;
  245. //TODO: needs setlocale(LC_NUMERIC, "C")?
  246. d = strtod(arg, &ptr);
  247. if (errno || ptr == arg || *ptr
  248. || d > (0xFFFFFFFFU / 1000) || d < 0
  249. ) {
  250. invarg_1_to_2(arg, errmsg); /* does not return */
  251. }
  252. ret = d * 1000;
  253. return ret;
  254. }
  255. static void do_set_can(char *dev, char **argv)
  256. {
  257. struct can_bittiming bt = {}, dbt = {};
  258. struct can_ctrlmode cm = {};
  259. char *keyword;
  260. static const char keywords[] ALIGN1 =
  261. "bitrate\0""sample-point\0""tq\0"
  262. "prop-seg\0""phase-seg1\0""phase-seg2\0""sjw\0"
  263. "dbitrate\0""dsample-point\0""dtq\0"
  264. "dprop-seg\0""dphase-seg1\0""dphase-seg2\0""dsjw\0"
  265. "loopback\0""listen-only\0""triple-sampling\0"
  266. "one-shot\0""berr-reporting\0"
  267. "fd\0""fd-non-iso\0""presume-ack\0"
  268. "cc-len8-dlc\0""restart\0""restart-ms\0"
  269. "termination\0";
  270. enum { ARG_bitrate = 0, ARG_sample_point, ARG_tq,
  271. ARG_prop_seg, ARG_phase_seg1, ARG_phase_seg2, ARG_sjw,
  272. ARG_dbitrate, ARG_dsample_point, ARG_dtq,
  273. ARG_dprop_seg, ARG_dphase_seg1, ARG_dphase_seg2, ARG_dsjw,
  274. ARG_loopback, ARG_listen_only, ARG_triple_sampling,
  275. ARG_one_shot, ARG_berr_reporting,
  276. ARG_fd, ARG_fd_non_iso, ARG_presume_ack,
  277. ARG_cc_len8_dlc, ARG_restart, ARG_restart_ms,
  278. ARG_termination };
  279. struct rtnl_handle rth;
  280. struct {
  281. struct nlmsghdr n;
  282. struct ifinfomsg i;
  283. char buf[1024];
  284. } req;
  285. size_t dev_len;
  286. struct rtattr *linkinfo, *data;
  287. smalluint key, param;
  288. memset(&req, 0, sizeof(req));
  289. req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
  290. req.n.nlmsg_flags = NLM_F_REQUEST;
  291. req.n.nlmsg_type = RTM_NEWLINK;
  292. req.i.ifi_family = preferred_family;
  293. xrtnl_open(&rth);
  294. req.i.ifi_index = xll_name_to_index(dev);
  295. dev_len = strlen(dev);
  296. if (dev_len < 2 || dev_len > IFNAMSIZ)
  297. invarg_1_to_2(dev, "dev");
  298. addattr_l(&req.n, sizeof(req), IFLA_IFNAME, dev, dev_len);
  299. linkinfo = NLMSG_TAIL(&req.n);
  300. addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
  301. addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, (void *)"can",
  302. strlen("can"));
  303. data = NLMSG_TAIL(&req.n);
  304. addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0);
  305. while (*argv) {
  306. key = index_in_substrings(keywords, *argv);
  307. keyword = *argv;
  308. //printf("%s: key: %d, *argv: %s\n", __func__, key, *argv);
  309. switch (key) {
  310. case ARG_bitrate:
  311. case ARG_tq:
  312. case ARG_prop_seg:
  313. case ARG_phase_seg1:
  314. case ARG_phase_seg2:
  315. case ARG_sjw: {
  316. uint32_t *val;
  317. NEXT_ARG();
  318. if (key == ARG_bitrate)
  319. val = &bt.bitrate;
  320. else if (key == ARG_tq)
  321. val = &bt.tq;
  322. else if (key == ARG_prop_seg)
  323. val = &bt.prop_seg;
  324. else if (key == ARG_phase_seg1)
  325. val = &bt.phase_seg1;
  326. else if (key == ARG_phase_seg2)
  327. val = &bt.phase_seg2;
  328. else
  329. val = &bt.sjw;
  330. *val = get_u32(*argv, keyword);
  331. break;
  332. }
  333. case ARG_sample_point: {
  334. NEXT_ARG();
  335. bt.sample_point = get_float_1000(*argv, keyword);
  336. break;
  337. }
  338. case ARG_dbitrate:
  339. case ARG_dtq:
  340. case ARG_dprop_seg:
  341. case ARG_dphase_seg1:
  342. case ARG_dphase_seg2:
  343. case ARG_dsjw: {
  344. uint32_t *val;
  345. NEXT_ARG();
  346. if (key == ARG_dbitrate)
  347. val = &dbt.bitrate;
  348. else if (key == ARG_dtq)
  349. val = &dbt.tq;
  350. else if (key == ARG_dprop_seg)
  351. val = &dbt.prop_seg;
  352. else if (key == ARG_dphase_seg1)
  353. val = &dbt.phase_seg1;
  354. else if (key == ARG_dphase_seg2)
  355. val = &dbt.phase_seg2;
  356. else
  357. val = &dbt.sjw;
  358. *val = get_u32(*argv, keyword);
  359. break;
  360. }
  361. case ARG_dsample_point: {
  362. NEXT_ARG();
  363. dbt.sample_point = get_float_1000(*argv, keyword);
  364. break;
  365. }
  366. case ARG_loopback:
  367. case ARG_listen_only:
  368. case ARG_triple_sampling:
  369. case ARG_one_shot:
  370. case ARG_berr_reporting:
  371. case ARG_fd:
  372. case ARG_fd_non_iso:
  373. case ARG_presume_ack:
  374. case ARG_cc_len8_dlc: {
  375. uint32_t flag = 0;
  376. NEXT_ARG();
  377. param = index_in_strings(str_on_off, *argv);
  378. if (param < 0)
  379. die_must_be_on_off(keyword);
  380. if (key == ARG_loopback)
  381. flag = CAN_CTRLMODE_LOOPBACK;
  382. else if (key == ARG_listen_only)
  383. flag = CAN_CTRLMODE_LISTENONLY;
  384. else if (key == ARG_triple_sampling)
  385. flag = CAN_CTRLMODE_3_SAMPLES;
  386. else if (key == ARG_one_shot)
  387. flag = CAN_CTRLMODE_ONE_SHOT;
  388. else if (key == ARG_berr_reporting)
  389. flag = CAN_CTRLMODE_BERR_REPORTING;
  390. else if (key == ARG_fd)
  391. flag = CAN_CTRLMODE_FD;
  392. else if (key == ARG_fd_non_iso)
  393. flag = CAN_CTRLMODE_FD_NON_ISO;
  394. else if (key == ARG_presume_ack)
  395. flag = CAN_CTRLMODE_PRESUME_ACK;
  396. else
  397. #if defined(CAN_CTRLMODE_CC_LEN8_DLC)
  398. flag = CAN_CTRLMODE_CC_LEN8_DLC;
  399. #else
  400. die_must_be_on_off(keyword);
  401. #endif
  402. cm.mask |= flag;
  403. if (param == PARM_on)
  404. cm.flags |= flag;
  405. break;
  406. }
  407. case ARG_restart: {
  408. uint32_t val = 1;
  409. /*NEXT_ARG(); - WRONG? */
  410. addattr_l(&req.n, sizeof(req), IFLA_CAN_RESTART, &val, sizeof(val));
  411. break;
  412. }
  413. case ARG_restart_ms: {
  414. uint32_t val;
  415. NEXT_ARG();
  416. val = get_u32(*argv, keyword);
  417. addattr_l(&req.n, sizeof(req), IFLA_CAN_RESTART_MS, &val, sizeof(val));
  418. break;
  419. }
  420. case ARG_termination: {
  421. uint16_t val;
  422. NEXT_ARG();
  423. val = get_u16(*argv, keyword);
  424. addattr_l(&req.n, sizeof(req), IFLA_CAN_TERMINATION, &val, sizeof(val));
  425. break;
  426. }
  427. default:
  428. break;
  429. }
  430. argv++;
  431. }
  432. if (bt.bitrate || bt.tq)
  433. addattr_l(&req.n, sizeof(req), IFLA_CAN_BITTIMING, &bt, sizeof(bt));
  434. if (cm.mask)
  435. addattr_l(&req.n, sizeof(req), IFLA_CAN_CTRLMODE, &cm, sizeof(cm));
  436. data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;
  437. linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo;
  438. if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
  439. xfunc_die();
  440. }
  441. static void set_type(char *type, char *dev, char **argv)
  442. {
  443. /* When we have more than just "type can ARGS" supported, maybe:
  444. static const char keywords[] ALIGN1 = ""
  445. IF_FEATURE_IP_LINK_CAN("can\0")
  446. ;
  447. typedef void FAST_FUNC(*ip_type_set_func_ptr_t)(char*, char**);
  448. static const ip_type_set_func_ptr_t funcs[] ALIGN_PTR = {
  449. IF_FEATURE_IP_LINK_CAN(do_set_can,)
  450. };
  451. ip_type_set_func_ptr_t func;
  452. int key;
  453. key = index_in_substrings(keywords, type);
  454. if (key < 0)
  455. invarg_1_to_2(type, "type");
  456. func = funcs[key];
  457. func(dev, argv);
  458. */
  459. if (strcmp(type, "can") != 0)
  460. invarg_1_to_2(type, "type");
  461. do_set_can(dev, argv);
  462. }
  463. #endif
  464. /* Return value becomes exitcode. It's okay to not return at all */
  465. static int do_set(char **argv)
  466. {
  467. char *dev = NULL;
  468. #if ENABLE_FEATURE_IP_LINK_CAN
  469. char *type = NULL;
  470. #endif
  471. uint32_t mask = 0;
  472. uint32_t flags = 0;
  473. int qlen = -1;
  474. int mtu = -1;
  475. int master = -1;
  476. int netns = -1;
  477. char *newaddr = NULL;
  478. char *newbrd = NULL;
  479. struct ifreq ifr0, ifr1;
  480. char *newname = NULL;
  481. int htype, halen;
  482. /* If you add stuff here, update iplink_full_usage */
  483. static const char keywords[] ALIGN1 =
  484. "up\0""down\0""name\0""mtu\0""qlen\0""multicast\0"
  485. "arp\0""promisc\0""address\0""netns\0"
  486. "master\0""nomaster\0"
  487. #if ENABLE_FEATURE_IP_LINK_CAN
  488. "type\0"
  489. #endif
  490. "dev\0" /* must be last */;
  491. enum { ARG_up = 0, ARG_down, ARG_name, ARG_mtu, ARG_qlen, ARG_multicast,
  492. ARG_arp, ARG_promisc, ARG_addr, ARG_netns,
  493. ARG_master, ARG_nomaster,
  494. #if ENABLE_FEATURE_IP_LINK_CAN
  495. ARG_type,
  496. #endif
  497. ARG_dev };
  498. smalluint key;
  499. while (*argv) {
  500. /* substring search ensures that e.g. "addr" and "address"
  501. * are both accepted */
  502. key = index_in_substrings(keywords, *argv);
  503. //printf("%s: key: %d, *argv: %s\n", __func__, key, *argv);
  504. if (key == ARG_up) {
  505. mask |= IFF_UP;
  506. flags |= IFF_UP;
  507. } else if (key == ARG_down) {
  508. mask |= IFF_UP;
  509. flags &= ~IFF_UP;
  510. } else if (key == ARG_name) {
  511. NEXT_ARG();
  512. newname = *argv;
  513. } else if (key == ARG_mtu) {
  514. NEXT_ARG();
  515. if (mtu != -1)
  516. duparg("mtu", *argv);
  517. mtu = get_unsigned(*argv, "mtu");
  518. } else if (key == ARG_qlen) {
  519. //TODO: txqueuelen, txqlen are synonyms to qlen
  520. NEXT_ARG();
  521. if (qlen != -1)
  522. duparg("qlen", *argv);
  523. qlen = get_unsigned(*argv, "qlen");
  524. } else if (key == ARG_addr) {
  525. NEXT_ARG();
  526. newaddr = *argv;
  527. } else if (key == ARG_master) {
  528. NEXT_ARG();
  529. master = xll_name_to_index(*argv);
  530. } else if (key == ARG_nomaster) {
  531. master = 0;
  532. } else if (key == ARG_netns) {
  533. NEXT_ARG();
  534. netns = get_unsigned(*argv, "netns");
  535. #if ENABLE_FEATURE_IP_LINK_CAN
  536. } else if (key == ARG_type) {
  537. NEXT_ARG();
  538. type = *argv;
  539. argv++;
  540. break;
  541. #endif
  542. } else if (key >= ARG_dev) {
  543. /* ^^^^^^ ">=" here results in "dev IFACE" treated as default */
  544. if (key == ARG_dev) {
  545. NEXT_ARG();
  546. }
  547. if (dev)
  548. duparg2("dev", *argv);
  549. dev = *argv;
  550. } else {
  551. /* "on|off" options */
  552. int param;
  553. NEXT_ARG();
  554. param = index_in_strings(str_on_off, *argv);
  555. if (key == ARG_multicast) {
  556. if (param < 0)
  557. die_must_be_on_off("multicast");
  558. mask |= IFF_MULTICAST;
  559. if (param == PARM_on)
  560. flags |= IFF_MULTICAST;
  561. else
  562. flags &= ~IFF_MULTICAST;
  563. } else if (key == ARG_arp) {
  564. if (param < 0)
  565. die_must_be_on_off("arp");
  566. mask |= IFF_NOARP;
  567. if (param == PARM_on)
  568. flags &= ~IFF_NOARP;
  569. else
  570. flags |= IFF_NOARP;
  571. } else if (key == ARG_promisc) {
  572. if (param < 0)
  573. die_must_be_on_off("promisc");
  574. mask |= IFF_PROMISC;
  575. if (param == PARM_on)
  576. flags |= IFF_PROMISC;
  577. else
  578. flags &= ~IFF_PROMISC;
  579. }
  580. }
  581. /* Other keywords recognized by iproute2-3.12.0: */
  582. #if 0
  583. } else if (matches(*argv, "broadcast") == 0 ||
  584. strcmp(*argv, "brd") == 0) {
  585. NEXT_ARG();
  586. len = ll_addr_a2n(abuf, sizeof(abuf), *argv);
  587. if (len < 0)
  588. return -1;
  589. addattr_l(&req->n, sizeof(*req), IFLA_BROADCAST, abuf, len);
  590. } else if (strcmp(*argv, "netns") == 0) {
  591. NEXT_ARG();
  592. if (netns != -1)
  593. duparg("netns", *argv);
  594. if ((netns = get_netns_fd(*argv)) >= 0)
  595. addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_FD, &netns, 4);
  596. else if (get_integer(&netns, *argv, 0) == 0)
  597. addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_PID, &netns, 4);
  598. else
  599. invarg_1_to_2(*argv, "netns");
  600. } else if (strcmp(*argv, "allmulticast") == 0) {
  601. NEXT_ARG();
  602. req->i.ifi_change |= IFF_ALLMULTI;
  603. if (strcmp(*argv, "on") == 0) {
  604. req->i.ifi_flags |= IFF_ALLMULTI;
  605. } else if (strcmp(*argv, "off") == 0) {
  606. req->i.ifi_flags &= ~IFF_ALLMULTI;
  607. } else
  608. return on_off("allmulticast", *argv);
  609. } else if (strcmp(*argv, "trailers") == 0) {
  610. NEXT_ARG();
  611. req->i.ifi_change |= IFF_NOTRAILERS;
  612. if (strcmp(*argv, "off") == 0) {
  613. req->i.ifi_flags |= IFF_NOTRAILERS;
  614. } else if (strcmp(*argv, "on") == 0) {
  615. req->i.ifi_flags &= ~IFF_NOTRAILERS;
  616. } else
  617. return on_off("trailers", *argv);
  618. } else if (strcmp(*argv, "vf") == 0) {
  619. struct rtattr *vflist;
  620. NEXT_ARG();
  621. if (get_integer(&vf, *argv, 0)) {
  622. invarg_1_to_2(*argv, "vf");
  623. }
  624. vflist = addattr_nest(&req->n, sizeof(*req),
  625. IFLA_VFINFO_LIST);
  626. len = iplink_parse_vf(vf, &argc, &argv, req);
  627. if (len < 0)
  628. return -1;
  629. addattr_nest_end(&req->n, vflist);
  630. } else if (matches(*argv, "master") == 0) {
  631. int ifindex;
  632. NEXT_ARG();
  633. ifindex = ll_name_to_index(*argv);
  634. if (!ifindex)
  635. invarg_1_to_2(*argv, "master");
  636. addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
  637. &ifindex, 4);
  638. } else if (matches(*argv, "nomaster") == 0) {
  639. int ifindex = 0;
  640. addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
  641. &ifindex, 4);
  642. } else if (matches(*argv, "dynamic") == 0) {
  643. NEXT_ARG();
  644. req->i.ifi_change |= IFF_DYNAMIC;
  645. if (strcmp(*argv, "on") == 0) {
  646. req->i.ifi_flags |= IFF_DYNAMIC;
  647. } else if (strcmp(*argv, "off") == 0) {
  648. req->i.ifi_flags &= ~IFF_DYNAMIC;
  649. } else
  650. return on_off("dynamic", *argv);
  651. } else if (matches(*argv, "alias") == 0) {
  652. NEXT_ARG();
  653. addattr_l(&req->n, sizeof(*req), IFLA_IFALIAS,
  654. *argv, strlen(*argv));
  655. argc--; argv++;
  656. break;
  657. } else if (strcmp(*argv, "group") == 0) {
  658. NEXT_ARG();
  659. if (*group != -1)
  660. duparg("group", *argv);
  661. if (rtnl_group_a2n(group, *argv))
  662. invarg_1_to_2(*argv, "group");
  663. } else if (strcmp(*argv, "mode") == 0) {
  664. int mode;
  665. NEXT_ARG();
  666. mode = get_link_mode(*argv);
  667. if (mode < 0)
  668. invarg_1_to_2(*argv, "mode");
  669. addattr8(&req->n, sizeof(*req), IFLA_LINKMODE, mode);
  670. } else if (strcmp(*argv, "state") == 0) {
  671. int state;
  672. NEXT_ARG();
  673. state = get_operstate(*argv);
  674. if (state < 0)
  675. invarg_1_to_2(*argv, "state");
  676. addattr8(&req->n, sizeof(*req), IFLA_OPERSTATE, state);
  677. } else if (matches(*argv, "numtxqueues") == 0) {
  678. NEXT_ARG();
  679. if (numtxqueues != -1)
  680. duparg("numtxqueues", *argv);
  681. if (get_integer(&numtxqueues, *argv, 0))
  682. invarg_1_to_2(*argv, "numtxqueues");
  683. addattr_l(&req->n, sizeof(*req), IFLA_NUM_TX_QUEUES,
  684. &numtxqueues, 4);
  685. } else if (matches(*argv, "numrxqueues") == 0) {
  686. NEXT_ARG();
  687. if (numrxqueues != -1)
  688. duparg("numrxqueues", *argv);
  689. if (get_integer(&numrxqueues, *argv, 0))
  690. invarg_1_to_2(*argv, "numrxqueues");
  691. addattr_l(&req->n, sizeof(*req), IFLA_NUM_RX_QUEUES,
  692. &numrxqueues, 4);
  693. }
  694. #endif
  695. argv++;
  696. }
  697. if (!dev) {
  698. bb_error_msg_and_die(bb_msg_requires_arg, "\"dev\"");
  699. }
  700. if (newaddr || newbrd) {
  701. halen = get_address(dev, &htype);
  702. if (newaddr) {
  703. parse_address(dev, htype, halen, newaddr, &ifr0);
  704. set_address(&ifr0, 0);
  705. }
  706. if (newbrd) {
  707. parse_address(dev, htype, halen, newbrd, &ifr1);
  708. set_address(&ifr1, 1);
  709. }
  710. }
  711. if (newname && strcmp(dev, newname)) {
  712. do_changename(dev, newname);
  713. dev = newname;
  714. }
  715. if (qlen != -1) {
  716. set_qlen(dev, qlen);
  717. }
  718. if (mtu != -1) {
  719. set_mtu(dev, mtu);
  720. }
  721. if (master != -1) {
  722. set_master(dev, master);
  723. }
  724. if (netns != -1) {
  725. set_netns(dev, netns);
  726. }
  727. if (mask)
  728. do_chflags(dev, flags, mask);
  729. #if ENABLE_FEATURE_IP_LINK_CAN
  730. if (type)
  731. set_type(type, dev, argv);
  732. #endif
  733. return 0;
  734. }
  735. static int ipaddr_list_link(char **argv)
  736. {
  737. preferred_family = AF_PACKET;
  738. return ipaddr_list_or_flush(argv, 0);
  739. }
  740. static void vlan_parse_opt(char **argv, struct nlmsghdr *n, unsigned int size)
  741. {
  742. static const char keywords[] ALIGN1 =
  743. "id\0"
  744. "protocol\0"
  745. "reorder_hdr\0"
  746. "gvrp\0"
  747. "mvrp\0"
  748. "loose_binding\0"
  749. ;
  750. static const char protocols[] ALIGN1 =
  751. "802.1q\0"
  752. "802.1ad\0"
  753. ;
  754. enum {
  755. ARG_id = 0,
  756. ARG_protocol,
  757. ARG_reorder_hdr,
  758. ARG_gvrp,
  759. ARG_mvrp,
  760. ARG_loose_binding,
  761. };
  762. enum {
  763. PROTO_8021Q = 0,
  764. PROTO_8021AD,
  765. };
  766. int arg;
  767. uint16_t id, proto;
  768. struct ifla_vlan_flags flags = {};
  769. while (*argv) {
  770. arg = index_in_substrings(keywords, *argv);
  771. if (arg < 0)
  772. invarg_1_to_2(*argv, "type vlan");
  773. NEXT_ARG();
  774. if (arg == ARG_id) {
  775. id = get_u16(*argv, "id");
  776. addattr_l(n, size, IFLA_VLAN_ID, &id, sizeof(id));
  777. } else if (arg == ARG_protocol) {
  778. arg = index_in_substrings(protocols, str_tolower(*argv));
  779. if (arg == PROTO_8021Q)
  780. proto = htons(ETH_P_8021Q);
  781. else if (arg == PROTO_8021AD)
  782. proto = htons(ETH_P_8021AD);
  783. else
  784. bb_error_msg_and_die("unknown VLAN encapsulation protocol '%s'",
  785. *argv);
  786. addattr_l(n, size, IFLA_VLAN_PROTOCOL, &proto, sizeof(proto));
  787. } else {
  788. int param = index_in_strings(str_on_off, *argv);
  789. if (param < 0)
  790. die_must_be_on_off(nth_string(keywords, arg));
  791. if (arg == ARG_reorder_hdr) {
  792. flags.mask |= VLAN_FLAG_REORDER_HDR;
  793. flags.flags &= ~VLAN_FLAG_REORDER_HDR;
  794. if (param == PARM_on)
  795. flags.flags |= VLAN_FLAG_REORDER_HDR;
  796. } else if (arg == ARG_gvrp) {
  797. flags.mask |= VLAN_FLAG_GVRP;
  798. flags.flags &= ~VLAN_FLAG_GVRP;
  799. if (param == PARM_on)
  800. flags.flags |= VLAN_FLAG_GVRP;
  801. } else if (arg == ARG_mvrp) {
  802. flags.mask |= VLAN_FLAG_MVRP;
  803. flags.flags &= ~VLAN_FLAG_MVRP;
  804. if (param == PARM_on)
  805. flags.flags |= VLAN_FLAG_MVRP;
  806. } else { /*if (arg == ARG_loose_binding) */
  807. flags.mask |= VLAN_FLAG_LOOSE_BINDING;
  808. flags.flags &= ~VLAN_FLAG_LOOSE_BINDING;
  809. if (param == PARM_on)
  810. flags.flags |= VLAN_FLAG_LOOSE_BINDING;
  811. }
  812. }
  813. argv++;
  814. }
  815. if (flags.mask)
  816. addattr_l(n, size, IFLA_VLAN_FLAGS, &flags, sizeof(flags));
  817. }
  818. static void vrf_parse_opt(char **argv, struct nlmsghdr *n, unsigned int size)
  819. {
  820. /* IFLA_VRF_TABLE is an enum, not a define -
  821. * can't test "defined(IFLA_VRF_TABLE)".
  822. */
  823. #if !defined(IFLA_VRF_MAX)
  824. # define IFLA_VRF_TABLE 1
  825. #endif
  826. uint32_t table;
  827. if (strcmp(*argv, "table") != 0)
  828. invarg_1_to_2(*argv, "type vrf");
  829. NEXT_ARG();
  830. table = get_u32(*argv, "table");
  831. addattr_l(n, size, IFLA_VRF_TABLE, &table, sizeof(table));
  832. }
  833. /* Return value becomes exitcode. It's okay to not return at all */
  834. static int do_add_or_delete(char **argv, const unsigned rtm)
  835. {
  836. static const char keywords[] ALIGN1 =
  837. "link\0""name\0""type\0""dev\0""address\0";
  838. enum {
  839. ARG_link,
  840. ARG_name,
  841. ARG_type,
  842. ARG_dev,
  843. ARG_address,
  844. };
  845. struct rtnl_handle rth;
  846. struct {
  847. struct nlmsghdr n;
  848. struct ifinfomsg i;
  849. char buf[1024];
  850. } req;
  851. smalluint arg;
  852. char *name_str = NULL;
  853. char *link_str = NULL;
  854. char *type_str = NULL;
  855. char *dev_str = NULL;
  856. char *address_str = NULL;
  857. memset(&req, 0, sizeof(req));
  858. req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
  859. req.n.nlmsg_flags = NLM_F_REQUEST;
  860. req.n.nlmsg_type = rtm;
  861. req.i.ifi_family = preferred_family;
  862. if (rtm == RTM_NEWLINK)
  863. req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL;
  864. /* NB: update iplink_full_usage if you extend this code */
  865. while (*argv) {
  866. arg = index_in_substrings(keywords, *argv);
  867. if (arg == ARG_type) {
  868. NEXT_ARG();
  869. type_str = *argv++;
  870. dbg("type_str:'%s'", type_str);
  871. break;
  872. }
  873. if (arg == ARG_link) {
  874. NEXT_ARG();
  875. link_str = *argv;
  876. dbg("link_str:'%s'", link_str);
  877. } else if (arg == ARG_name) {
  878. NEXT_ARG();
  879. name_str = *argv;
  880. dbg("name_str:'%s'", name_str);
  881. } else if (arg == ARG_address) {
  882. NEXT_ARG();
  883. address_str = *argv;
  884. dbg("address_str:'%s'", address_str);
  885. } else {
  886. if (arg == ARG_dev) {
  887. if (dev_str)
  888. duparg(*argv, "dev");
  889. NEXT_ARG();
  890. }
  891. dev_str = *argv;
  892. dbg("dev_str:'%s'", dev_str);
  893. }
  894. argv++;
  895. }
  896. xrtnl_open(&rth);
  897. ll_init_map(&rth);
  898. if (type_str) {
  899. struct rtattr *linkinfo = NLMSG_TAIL(&req.n);
  900. addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
  901. addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type_str,
  902. strlen(type_str));
  903. if (*argv) {
  904. struct rtattr *data = NLMSG_TAIL(&req.n);
  905. addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0);
  906. if (strcmp(type_str, "vlan") == 0)
  907. vlan_parse_opt(argv, &req.n, sizeof(req));
  908. else if (strcmp(type_str, "vrf") == 0)
  909. vrf_parse_opt(argv, &req.n, sizeof(req));
  910. data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;
  911. }
  912. linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo;
  913. }
  914. /* Allow "ip link add dev" and "ip link add name" */
  915. if (!name_str)
  916. name_str = dev_str;
  917. else if (!dev_str)
  918. dev_str = name_str;
  919. /* else if (!strcmp(name_str, dev_str))
  920. name_str = dev_str; */
  921. if (rtm != RTM_NEWLINK) {
  922. if (!dev_str)
  923. return 1; /* Need a device to delete */
  924. req.i.ifi_index = xll_name_to_index(dev_str);
  925. } else {
  926. if (link_str) {
  927. int idx = xll_name_to_index(link_str);
  928. addattr_l(&req.n, sizeof(req), IFLA_LINK, &idx, 4);
  929. }
  930. if (address_str) {
  931. unsigned char abuf[32];
  932. int len = ll_addr_a2n(abuf, sizeof(abuf), address_str);
  933. dbg("address len:%d", len);
  934. if (len < 0)
  935. return -1;
  936. addattr_l(&req.n, sizeof(req), IFLA_ADDRESS, abuf, len);
  937. }
  938. }
  939. if (name_str) {
  940. const size_t name_len = strlen(name_str) + 1;
  941. if (name_len < 2 || name_len > IFNAMSIZ)
  942. invarg_1_to_2(name_str, "name");
  943. addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name_str, name_len);
  944. }
  945. if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
  946. return 2;
  947. return 0;
  948. }
  949. /* Return value becomes exitcode. It's okay to not return at all */
  950. int FAST_FUNC do_iplink(char **argv)
  951. {
  952. static const char keywords[] ALIGN1 =
  953. "add\0""delete\0""set\0""show\0""lst\0""list\0";
  954. xfunc_error_retval = 2; //TODO: move up to "ip"? Is it the common rule for all "ip" tools?
  955. if (*argv) {
  956. int key = index_in_substrings(keywords, *argv);
  957. if (key < 0) /* invalid argument */
  958. invarg_1_to_2(*argv, applet_name);
  959. argv++;
  960. if (key <= 1) /* add/delete */
  961. return do_add_or_delete(argv, key ? RTM_DELLINK : RTM_NEWLINK);
  962. if (key == 2) /* set */
  963. return do_set(argv);
  964. }
  965. /* show, lst, list */
  966. return ipaddr_list_link(argv);
  967. }