rtsock.c 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426
  1. /* $OpenBSD: rtsock.c,v 1.166 2015/07/18 21:58:06 mpi Exp $ */
  2. /* $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $ */
  3. /*
  4. * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the project nor the names of its contributors
  16. * may be used to endorse or promote products derived from this software
  17. * without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
  20. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22. * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
  23. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  25. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  26. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  27. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  28. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  29. * SUCH DAMAGE.
  30. */
  31. /*
  32. * Copyright (c) 1988, 1991, 1993
  33. * The Regents of the University of California. All rights reserved.
  34. *
  35. * Redistribution and use in source and binary forms, with or without
  36. * modification, are permitted provided that the following conditions
  37. * are met:
  38. * 1. Redistributions of source code must retain the above copyright
  39. * notice, this list of conditions and the following disclaimer.
  40. * 2. Redistributions in binary form must reproduce the above copyright
  41. * notice, this list of conditions and the following disclaimer in the
  42. * documentation and/or other materials provided with the distribution.
  43. * 3. Neither the name of the University nor the names of its contributors
  44. * may be used to endorse or promote products derived from this software
  45. * without specific prior written permission.
  46. *
  47. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  48. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  49. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  50. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  51. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  52. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  53. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  54. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  55. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  56. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  57. * SUCH DAMAGE.
  58. *
  59. * @(#)rtsock.c 8.6 (Berkeley) 2/11/95
  60. */
  61. #include <sys/param.h>
  62. #include <sys/systm.h>
  63. #include <sys/proc.h>
  64. #include <sys/sysctl.h>
  65. #include <sys/mbuf.h>
  66. #include <sys/socket.h>
  67. #include <sys/socketvar.h>
  68. #include <sys/domain.h>
  69. #include <sys/protosw.h>
  70. #include <net/if.h>
  71. #include <net/if_var.h>
  72. #include <net/route.h>
  73. #include <net/raw_cb.h>
  74. #ifdef MPLS
  75. #include <netmpls/mpls.h>
  76. #endif
  77. #include <sys/stdarg.h>
  78. #include <sys/kernel.h>
  79. #include <sys/timeout.h>
  80. struct sockaddr route_dst = { 2, PF_ROUTE, };
  81. struct sockaddr route_src = { 2, PF_ROUTE, };
  82. struct sockproto route_proto = { PF_ROUTE, };
  83. struct walkarg {
  84. int w_op, w_arg, w_given, w_needed, w_tmemsize;
  85. caddr_t w_where, w_tmem;
  86. };
  87. int route_ctloutput(int, struct socket *, int, int, struct mbuf **);
  88. void route_input(struct mbuf *m0, ...);
  89. struct mbuf *rt_msg1(int, struct rt_addrinfo *);
  90. int rt_msg2(int, int, struct rt_addrinfo *, caddr_t,
  91. struct walkarg *);
  92. void rt_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *);
  93. struct routecb {
  94. struct rawcb rcb;
  95. struct timeout timeout;
  96. unsigned int msgfilter;
  97. unsigned int flags;
  98. u_int rtableid;
  99. };
  100. #define sotoroutecb(so) ((struct routecb *)(so)->so_pcb)
  101. struct route_cb {
  102. int ip_count;
  103. int ip6_count;
  104. int mpls_count;
  105. int any_count;
  106. };
  107. struct route_cb route_cb;
  108. /*
  109. * These flags and timeout are used for indicating to userland (via a
  110. * RTM_DESYNC msg) when the route socket has overflowed and messages
  111. * have been lost.
  112. */
  113. #define ROUTECB_FLAG_DESYNC 0x1 /* Route socket out of memory */
  114. #define ROUTECB_FLAG_FLUSH 0x2 /* Wait until socket is empty before
  115. queueing more packets */
  116. #define ROUTE_DESYNC_RESEND_TIMEOUT (hz / 5) /* In hz */
  117. void rt_senddesync(void *);
  118. int
  119. route_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
  120. struct mbuf *control, struct proc *p)
  121. {
  122. struct rawcb *rp;
  123. struct routecb *rop;
  124. int s, af;
  125. int error = 0;
  126. s = splsoftnet();
  127. rp = sotorawcb(so);
  128. switch (req) {
  129. case PRU_ATTACH:
  130. /*
  131. * use the rawcb but allocate a routecb, this
  132. * code does not care about the additional fields
  133. * and works directly on the raw socket.
  134. */
  135. rop = malloc(sizeof(struct routecb), M_PCB, M_WAITOK|M_ZERO);
  136. rp = &rop->rcb;
  137. so->so_pcb = rp;
  138. /* Init the timeout structure */
  139. timeout_set(&((struct routecb *)rp)->timeout, rt_senddesync, rp);
  140. /*
  141. * Don't call raw_usrreq() in the attach case, because
  142. * we want to allow non-privileged processes to listen
  143. * on and send "safe" commands to the routing socket.
  144. */
  145. if (curproc == 0)
  146. error = EACCES;
  147. else
  148. error = raw_attach(so, (int)(long)nam);
  149. if (error) {
  150. free(rp, M_PCB, 0);
  151. splx(s);
  152. return (error);
  153. }
  154. rop->rtableid = curproc->p_p->ps_rtableid;
  155. af = rp->rcb_proto.sp_protocol;
  156. if (af == AF_INET)
  157. route_cb.ip_count++;
  158. else if (af == AF_INET6)
  159. route_cb.ip6_count++;
  160. #ifdef MPLS
  161. else if (af == AF_MPLS)
  162. route_cb.mpls_count++;
  163. #endif
  164. rp->rcb_faddr = &route_src;
  165. route_cb.any_count++;
  166. soisconnected(so);
  167. so->so_options |= SO_USELOOPBACK;
  168. break;
  169. case PRU_RCVD:
  170. rop = (struct routecb *)rp;
  171. /*
  172. * If we are in a FLUSH state, check if the buffer is
  173. * empty so that we can clear the flag.
  174. */
  175. if (((rop->flags & ROUTECB_FLAG_FLUSH) != 0) &&
  176. ((sbspace(&rp->rcb_socket->so_rcv) ==
  177. rp->rcb_socket->so_rcv.sb_hiwat)))
  178. rop->flags &= ~ROUTECB_FLAG_FLUSH;
  179. break;
  180. case PRU_DETACH:
  181. if (rp) {
  182. timeout_del(&((struct routecb *)rp)->timeout);
  183. af = rp->rcb_proto.sp_protocol;
  184. if (af == AF_INET)
  185. route_cb.ip_count--;
  186. else if (af == AF_INET6)
  187. route_cb.ip6_count--;
  188. #ifdef MPLS
  189. else if (af == AF_MPLS)
  190. route_cb.mpls_count--;
  191. #endif
  192. route_cb.any_count--;
  193. }
  194. /* FALLTHROUGH */
  195. default:
  196. error = raw_usrreq(so, req, m, nam, control, p);
  197. }
  198. splx(s);
  199. return (error);
  200. }
  201. int
  202. route_ctloutput(int op, struct socket *so, int level, int optname,
  203. struct mbuf **mp)
  204. {
  205. struct routecb *rop = sotoroutecb(so);
  206. struct mbuf *m = *mp;
  207. int error = 0;
  208. unsigned int tid;
  209. if (level != AF_ROUTE) {
  210. error = EINVAL;
  211. if (op == PRCO_SETOPT && *mp)
  212. m_free(*mp);
  213. return (error);
  214. }
  215. switch (op) {
  216. case PRCO_SETOPT:
  217. switch (optname) {
  218. case ROUTE_MSGFILTER:
  219. if (m == NULL || m->m_len != sizeof(unsigned int))
  220. error = EINVAL;
  221. else
  222. rop->msgfilter = *mtod(m, unsigned int *);
  223. break;
  224. case ROUTE_TABLEFILTER:
  225. if (m == NULL || m->m_len != sizeof(unsigned int)) {
  226. error = EINVAL;
  227. break;
  228. }
  229. tid = *mtod(m, unsigned int *);
  230. if (tid != RTABLE_ANY && !rtable_exists(tid))
  231. error = ENOENT;
  232. else
  233. rop->rtableid = tid;
  234. break;
  235. default:
  236. error = ENOPROTOOPT;
  237. break;
  238. }
  239. if (m)
  240. m_free(m);
  241. break;
  242. case PRCO_GETOPT:
  243. switch (optname) {
  244. case ROUTE_MSGFILTER:
  245. *mp = m = m_get(M_WAIT, MT_SOOPTS);
  246. m->m_len = sizeof(unsigned int);
  247. *mtod(m, unsigned int *) = rop->msgfilter;
  248. break;
  249. case ROUTE_TABLEFILTER:
  250. *mp = m = m_get(M_WAIT, MT_SOOPTS);
  251. m->m_len = sizeof(unsigned int);
  252. *mtod(m, unsigned int *) = rop->rtableid;
  253. break;
  254. default:
  255. error = ENOPROTOOPT;
  256. break;
  257. }
  258. }
  259. return (error);
  260. }
  261. void
  262. rt_senddesync(void *data)
  263. {
  264. struct rawcb *rp;
  265. struct routecb *rop;
  266. struct mbuf *desync_mbuf;
  267. rp = (struct rawcb *)data;
  268. rop = (struct routecb *)rp;
  269. /* If we are in a DESYNC state, try to send a RTM_DESYNC packet */
  270. if ((rop->flags & ROUTECB_FLAG_DESYNC) != 0) {
  271. /*
  272. * If we fail to alloc memory or if sbappendaddr()
  273. * fails, re-add timeout and try again.
  274. */
  275. desync_mbuf = rt_msg1(RTM_DESYNC, NULL);
  276. if ((desync_mbuf != NULL) &&
  277. (sbappendaddr(&rp->rcb_socket->so_rcv, &route_src,
  278. desync_mbuf, (struct mbuf *)NULL) != 0)) {
  279. rop->flags &= ~ROUTECB_FLAG_DESYNC;
  280. sorwakeup(rp->rcb_socket);
  281. } else {
  282. m_freem(desync_mbuf);
  283. /* Re-add timeout to try sending msg again */
  284. timeout_add(&rop->timeout, ROUTE_DESYNC_RESEND_TIMEOUT);
  285. }
  286. }
  287. }
  288. void
  289. route_input(struct mbuf *m0, ...)
  290. {
  291. struct rawcb *rp;
  292. struct routecb *rop;
  293. struct rt_msghdr *rtm;
  294. struct mbuf *m = m0;
  295. int sockets = 0;
  296. struct socket *last = NULL;
  297. va_list ap;
  298. struct sockproto *proto;
  299. struct sockaddr *sosrc, *sodst;
  300. va_start(ap, m0);
  301. proto = va_arg(ap, struct sockproto *);
  302. sosrc = va_arg(ap, struct sockaddr *);
  303. sodst = va_arg(ap, struct sockaddr *);
  304. va_end(ap);
  305. /* ensure that we can access the rtm_type via mtod() */
  306. if (m->m_len < offsetof(struct rt_msghdr, rtm_type) + 1) {
  307. m_freem(m);
  308. return;
  309. }
  310. LIST_FOREACH(rp, &rawcb, rcb_list) {
  311. if (rp->rcb_socket->so_state & SS_CANTRCVMORE)
  312. continue;
  313. if (rp->rcb_proto.sp_family != proto->sp_family)
  314. continue;
  315. if (rp->rcb_proto.sp_protocol && proto->sp_protocol &&
  316. rp->rcb_proto.sp_protocol != proto->sp_protocol)
  317. continue;
  318. /*
  319. * We assume the lower level routines have
  320. * placed the address in a canonical format
  321. * suitable for a structure comparison.
  322. *
  323. * Note that if the lengths are not the same
  324. * the comparison will fail at the first byte.
  325. */
  326. #define equal(a1, a2) \
  327. (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
  328. if (rp->rcb_laddr && !equal(rp->rcb_laddr, sodst))
  329. continue;
  330. if (rp->rcb_faddr && !equal(rp->rcb_faddr, sosrc))
  331. continue;
  332. /* filter messages that the process does not want */
  333. rop = (struct routecb *)rp;
  334. rtm = mtod(m, struct rt_msghdr *);
  335. /* but RTM_DESYNC can't be filtered */
  336. if (rtm->rtm_type != RTM_DESYNC && rop->msgfilter != 0 &&
  337. !(rop->msgfilter & (1 << rtm->rtm_type)))
  338. continue;
  339. switch (rtm->rtm_type) {
  340. case RTM_IFANNOUNCE:
  341. case RTM_DESYNC:
  342. /* no tableid */
  343. break;
  344. case RTM_RESOLVE:
  345. case RTM_NEWADDR:
  346. case RTM_DELADDR:
  347. case RTM_IFINFO:
  348. /* check against rdomain id */
  349. if (rop->rtableid != RTABLE_ANY &&
  350. rtable_l2(rop->rtableid) != rtm->rtm_tableid)
  351. continue;
  352. break;
  353. default:
  354. /* check against rtable id */
  355. if (rop->rtableid != RTABLE_ANY &&
  356. rop->rtableid != rtm->rtm_tableid)
  357. continue;
  358. break;
  359. }
  360. /*
  361. * Check to see if the flush flag is set. If so, don't queue
  362. * any more messages until the flag is cleared.
  363. */
  364. if ((rop->flags & ROUTECB_FLAG_FLUSH) != 0)
  365. continue;
  366. if (last) {
  367. struct mbuf *n;
  368. if ((n = m_copym(m, 0, M_COPYALL, M_NOWAIT)) != NULL) {
  369. if (sbspace(&last->so_rcv) < (2 * MSIZE) ||
  370. sbappendaddr(&last->so_rcv, sosrc,
  371. n, (struct mbuf *)NULL) == 0) {
  372. /*
  373. * Flag socket as desync'ed and
  374. * flush required
  375. */
  376. sotoroutecb(last)->flags |=
  377. ROUTECB_FLAG_DESYNC |
  378. ROUTECB_FLAG_FLUSH;
  379. rt_senddesync((void *) sotorawcb(last));
  380. m_freem(n);
  381. } else {
  382. sorwakeup(last);
  383. sockets++;
  384. }
  385. }
  386. }
  387. last = rp->rcb_socket;
  388. }
  389. if (last) {
  390. if (sbspace(&last->so_rcv) < (2 * MSIZE) ||
  391. sbappendaddr(&last->so_rcv, sosrc,
  392. m, (struct mbuf *)NULL) == 0) {
  393. /* Flag socket as desync'ed and flush required */
  394. sotoroutecb(last)->flags |=
  395. ROUTECB_FLAG_DESYNC | ROUTECB_FLAG_FLUSH;
  396. rt_senddesync((void *) sotorawcb(last));
  397. m_freem(m);
  398. } else {
  399. sorwakeup(last);
  400. sockets++;
  401. }
  402. } else
  403. m_freem(m);
  404. }
  405. int
  406. route_output(struct mbuf *m, ...)
  407. {
  408. struct rt_msghdr *rtm = NULL;
  409. struct rtentry *rt = NULL;
  410. struct rtentry *saved_nrt = NULL;
  411. struct rt_addrinfo info;
  412. int len, newgate, error = 0;
  413. struct ifnet *ifp = NULL;
  414. struct ifaddr *ifa = NULL;
  415. struct socket *so;
  416. struct rawcb *rp = NULL;
  417. struct sockaddr_rtlabel sa_rl;
  418. #ifdef MPLS
  419. struct sockaddr_mpls sa_mpls, *psa_mpls;
  420. #endif
  421. va_list ap;
  422. u_int tableid;
  423. u_int8_t prio;
  424. u_char vers;
  425. va_start(ap, m);
  426. so = va_arg(ap, struct socket *);
  427. va_end(ap);
  428. info.rti_info[RTAX_DST] = NULL; /* for error handling (goto flush) */
  429. if (m == NULL || ((m->m_len < sizeof(int32_t)) &&
  430. (m = m_pullup(m, sizeof(int32_t))) == 0))
  431. return (ENOBUFS);
  432. if ((m->m_flags & M_PKTHDR) == 0)
  433. panic("route_output");
  434. len = m->m_pkthdr.len;
  435. if (len < offsetof(struct rt_msghdr, rtm_type) + 1 ||
  436. len != mtod(m, struct rt_msghdr *)->rtm_msglen) {
  437. error = EINVAL;
  438. goto fail;
  439. }
  440. vers = mtod(m, struct rt_msghdr *)->rtm_version;
  441. switch (vers) {
  442. case RTM_VERSION:
  443. if (len < sizeof(struct rt_msghdr)) {
  444. error = EINVAL;
  445. goto fail;
  446. }
  447. if (len > RTM_MAXSIZE) {
  448. error = EMSGSIZE;
  449. goto fail;
  450. }
  451. rtm = malloc(len, M_RTABLE, M_NOWAIT);
  452. if (rtm == NULL) {
  453. error = ENOBUFS;
  454. goto fail;
  455. }
  456. m_copydata(m, 0, len, (caddr_t)rtm);
  457. break;
  458. default:
  459. error = EPROTONOSUPPORT;
  460. goto fail;
  461. }
  462. rtm->rtm_pid = curproc->p_p->ps_pid;
  463. if (rtm->rtm_hdrlen == 0) /* old client */
  464. rtm->rtm_hdrlen = sizeof(struct rt_msghdr);
  465. if (len < rtm->rtm_hdrlen) {
  466. error = EINVAL;
  467. goto fail;
  468. }
  469. /* Verify that the caller is sending an appropriate message early */
  470. switch (rtm->rtm_type) {
  471. case RTM_ADD:
  472. case RTM_DELETE:
  473. case RTM_GET:
  474. case RTM_CHANGE:
  475. case RTM_LOCK:
  476. break;
  477. default:
  478. error = EOPNOTSUPP;
  479. goto fail;
  480. }
  481. /*
  482. * Verify that the caller has the appropriate privilege; RTM_GET
  483. * is the only operation the non-superuser is allowed.
  484. */
  485. if (rtm->rtm_type != RTM_GET && suser(curproc, 0) != 0) {
  486. error = EACCES;
  487. goto fail;
  488. }
  489. tableid = rtm->rtm_tableid;
  490. if (!rtable_exists(tableid)) {
  491. if (rtm->rtm_type == RTM_ADD) {
  492. if ((error = rtable_add(tableid)) != 0)
  493. goto flush;
  494. } else {
  495. error = EINVAL;
  496. goto flush;
  497. }
  498. }
  499. /* Do not let userland play with kernel-only flags. */
  500. if ((rtm->rtm_flags & (RTF_LOCAL|RTF_BROADCAST)) != 0) {
  501. error = EINVAL;
  502. goto fail;
  503. }
  504. /* make sure that kernel-only bits are not set */
  505. rtm->rtm_priority &= RTP_MASK;
  506. rtm->rtm_flags &= ~(RTF_DONE|RTF_CLONED);
  507. rtm->rtm_fmask &= RTF_FMASK;
  508. if (rtm->rtm_priority != 0) {
  509. if (rtm->rtm_priority > RTP_MAX ||
  510. rtm->rtm_priority == RTP_LOCAL) {
  511. error = EINVAL;
  512. goto fail;
  513. }
  514. prio = rtm->rtm_priority;
  515. } else if (rtm->rtm_type != RTM_ADD)
  516. prio = RTP_ANY;
  517. else if (rtm->rtm_flags & RTF_STATIC)
  518. prio = 0;
  519. else
  520. prio = RTP_DEFAULT;
  521. bzero(&info, sizeof(info));
  522. info.rti_addrs = rtm->rtm_addrs;
  523. rt_xaddrs(rtm->rtm_hdrlen + (caddr_t)rtm, len + (caddr_t)rtm, &info);
  524. info.rti_flags = rtm->rtm_flags;
  525. if (info.rti_info[RTAX_DST] == NULL ||
  526. info.rti_info[RTAX_DST]->sa_family >= AF_MAX ||
  527. (info.rti_info[RTAX_GATEWAY] != NULL &&
  528. info.rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX) ||
  529. info.rti_info[RTAX_GENMASK] != NULL) {
  530. error = EINVAL;
  531. goto flush;
  532. }
  533. #ifdef MPLS
  534. info.rti_mpls = rtm->rtm_mpls;
  535. #endif
  536. if (info.rti_info[RTAX_GATEWAY] != NULL &&
  537. info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK &&
  538. (info.rti_flags & RTF_CLONING) == 0) {
  539. info.rti_flags |= RTF_LLINFO;
  540. }
  541. switch (rtm->rtm_type) {
  542. case RTM_ADD:
  543. if (info.rti_info[RTAX_GATEWAY] == NULL) {
  544. error = EINVAL;
  545. goto flush;
  546. }
  547. error = rtrequest1(rtm->rtm_type, &info, prio, &saved_nrt,
  548. tableid);
  549. if (error == 0 && saved_nrt) {
  550. rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
  551. &saved_nrt->rt_rmx);
  552. saved_nrt->rt_refcnt--;
  553. /* write back the priority the kernel used */
  554. rtm->rtm_priority = saved_nrt->rt_priority & RTP_MASK;
  555. rtm->rtm_index = saved_nrt->rt_ifp->if_index;
  556. rtm->rtm_flags = saved_nrt->rt_flags;
  557. }
  558. break;
  559. case RTM_DELETE:
  560. error = rtrequest1(rtm->rtm_type, &info, prio, &saved_nrt,
  561. tableid);
  562. if (error == 0) {
  563. (rt = saved_nrt)->rt_refcnt++;
  564. goto report;
  565. }
  566. break;
  567. case RTM_GET:
  568. case RTM_CHANGE:
  569. case RTM_LOCK:
  570. if (!rtable_exists(tableid)) {
  571. error = EAFNOSUPPORT;
  572. goto flush;
  573. }
  574. rt = rtable_lookup(tableid, info.rti_info[RTAX_DST],
  575. info.rti_info[RTAX_NETMASK]);
  576. if (rt == NULL) {
  577. error = ESRCH;
  578. goto flush;
  579. }
  580. #ifndef SMALL_KERNEL
  581. /* First find the right priority. */
  582. rt = rtable_mpath_match(tableid, rt, NULL, prio);
  583. if (rt == NULL) {
  584. error = ESRCH;
  585. goto flush;
  586. }
  587. /*
  588. * For RTM_CHANGE/LOCK, if we got multipath routes,
  589. * a matching RTAX_GATEWAY is required.
  590. * OR
  591. * If a gateway is specified then RTM_GET and
  592. * RTM_LOCK must match the gateway no matter
  593. * what even in the non multipath case.
  594. */
  595. if ((rt->rt_flags & RTF_MPATH) ||
  596. (info.rti_info[RTAX_GATEWAY] && rtm->rtm_type !=
  597. RTM_CHANGE)) {
  598. rt = rtable_mpath_match(tableid, rt,
  599. info.rti_info[RTAX_GATEWAY], prio);
  600. if (rt == NULL) {
  601. error = ESRCH;
  602. goto flush;
  603. }
  604. /*
  605. * Only RTM_GET may use an empty gateway
  606. * on multipath routes
  607. */
  608. if (info.rti_info[RTAX_GATEWAY] == NULL &&
  609. rtm->rtm_type != RTM_GET) {
  610. rt = NULL;
  611. error = ESRCH;
  612. goto flush;
  613. }
  614. }
  615. #endif
  616. rt->rt_refcnt++;
  617. /*
  618. * RTM_CHANGE/LOCK need a perfect match, rn_lookup()
  619. * returns a perfect match in case a netmask is specified.
  620. * For host routes only a longest prefix match is returned
  621. * so it is necessary to compare the existence of the netmaks.
  622. * If both have a netmask rn_lookup() did a perfect match and
  623. * if none of them have a netmask both are host routes which is
  624. * also a perfect match.
  625. */
  626. if (rtm->rtm_type != RTM_GET &&
  627. !rt_mask(rt) != !info.rti_info[RTAX_NETMASK]) {
  628. error = ESRCH;
  629. goto flush;
  630. }
  631. switch (rtm->rtm_type) {
  632. case RTM_GET:
  633. report:
  634. info.rti_info[RTAX_DST] = rt_key(rt);
  635. info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
  636. info.rti_info[RTAX_NETMASK] = rt_mask(rt);
  637. info.rti_info[RTAX_LABEL] =
  638. rtlabel_id2sa(rt->rt_labelid, &sa_rl);
  639. #ifdef MPLS
  640. if (rt->rt_flags & RTF_MPLS) {
  641. bzero(&sa_mpls, sizeof(sa_mpls));
  642. sa_mpls.smpls_family = AF_MPLS;
  643. sa_mpls.smpls_len = sizeof(sa_mpls);
  644. sa_mpls.smpls_label = ((struct rt_mpls *)
  645. rt->rt_llinfo)->mpls_label;
  646. info.rti_info[RTAX_SRC] =
  647. (struct sockaddr *)&sa_mpls;
  648. info.rti_mpls = ((struct rt_mpls *)
  649. rt->rt_llinfo)->mpls_operation;
  650. rtm->rtm_mpls = info.rti_mpls;
  651. }
  652. #endif
  653. info.rti_info[RTAX_IFP] = NULL;
  654. info.rti_info[RTAX_IFA] = NULL;
  655. if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA) &&
  656. (ifp = rt->rt_ifp) != NULL) {
  657. info.rti_info[RTAX_IFP] =
  658. (struct sockaddr *)ifp->if_sadl;
  659. info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
  660. if (ifp->if_flags & IFF_POINTOPOINT)
  661. info.rti_info[RTAX_BRD] =
  662. rt->rt_ifa->ifa_dstaddr;
  663. else
  664. info.rti_info[RTAX_BRD] = NULL;
  665. rtm->rtm_index = ifp->if_index;
  666. }
  667. len = rt_msg2(rtm->rtm_type, RTM_VERSION, &info, NULL,
  668. NULL);
  669. if (len > rtm->rtm_msglen) {
  670. struct rt_msghdr *new_rtm;
  671. new_rtm = malloc(len, M_RTABLE, M_NOWAIT);
  672. if (new_rtm == NULL) {
  673. error = ENOBUFS;
  674. goto flush;
  675. }
  676. memcpy(new_rtm, rtm, rtm->rtm_msglen);
  677. free(rtm, M_RTABLE, 0);
  678. rtm = new_rtm;
  679. }
  680. rt_msg2(rtm->rtm_type, RTM_VERSION, &info, (caddr_t)rtm,
  681. NULL);
  682. rtm->rtm_flags = rt->rt_flags;
  683. rtm->rtm_use = 0;
  684. rtm->rtm_priority = rt->rt_priority & RTP_MASK;
  685. rt_getmetrics(&rt->rt_rmx, &rtm->rtm_rmx);
  686. rtm->rtm_addrs = info.rti_addrs;
  687. break;
  688. case RTM_CHANGE:
  689. newgate = 0;
  690. if (info.rti_info[RTAX_GATEWAY] != NULL)
  691. if (rt->rt_gateway == NULL ||
  692. bcmp(rt->rt_gateway,
  693. info.rti_info[RTAX_GATEWAY],
  694. info.rti_info[RTAX_GATEWAY]->sa_len)) {
  695. newgate = 1;
  696. }
  697. if (info.rti_info[RTAX_GATEWAY] != NULL &&
  698. (error = rt_setgate(rt, info.rti_info[RTAX_GATEWAY],
  699. tableid)))
  700. goto flush;
  701. /*
  702. * new gateway could require new ifaddr, ifp;
  703. * flags may also be different; ifp may be specified
  704. * by ll sockaddr when protocol address is ambiguous
  705. */
  706. if (newgate || info.rti_info[RTAX_IFP] != NULL ||
  707. info.rti_info[RTAX_IFA] != NULL) {
  708. if ((error = rt_getifa(&info, tableid)) != 0)
  709. goto flush;
  710. ifa = info.rti_ifa;
  711. }
  712. if (ifa) {
  713. if (rt->rt_ifa != ifa) {
  714. if (rt->rt_ifa->ifa_rtrequest)
  715. rt->rt_ifa->ifa_rtrequest(
  716. RTM_DELETE, rt);
  717. ifafree(rt->rt_ifa);
  718. rt->rt_ifa = ifa;
  719. ifa->ifa_refcnt++;
  720. rt->rt_ifp = ifa->ifa_ifp;
  721. #ifndef SMALL_KERNEL
  722. /* recheck link state after ifp change*/
  723. rt_if_linkstate_change(rt, rt->rt_ifp,
  724. tableid);
  725. #endif
  726. }
  727. }
  728. #ifdef MPLS
  729. if ((rtm->rtm_flags & RTF_MPLS) &&
  730. info.rti_info[RTAX_SRC] != NULL) {
  731. struct rt_mpls *rt_mpls;
  732. psa_mpls = (struct sockaddr_mpls *)
  733. info.rti_info[RTAX_SRC];
  734. if (rt->rt_llinfo == NULL) {
  735. rt->rt_llinfo =
  736. malloc(sizeof(struct rt_mpls),
  737. M_TEMP, M_NOWAIT|M_ZERO);
  738. }
  739. if (rt->rt_llinfo == NULL) {
  740. error = ENOMEM;
  741. goto flush;
  742. }
  743. rt_mpls = (struct rt_mpls *)rt->rt_llinfo;
  744. if (psa_mpls != NULL) {
  745. rt_mpls->mpls_label =
  746. psa_mpls->smpls_label;
  747. }
  748. rt_mpls->mpls_operation = info.rti_mpls;
  749. /* XXX: set experimental bits */
  750. rt->rt_flags |= RTF_MPLS;
  751. } else if (newgate || ((rtm->rtm_fmask & RTF_MPLS) &&
  752. !(rtm->rtm_flags & RTF_MPLS))) {
  753. /* if gateway changed remove MPLS information */
  754. if (rt->rt_llinfo != NULL &&
  755. rt->rt_flags & RTF_MPLS) {
  756. free(rt->rt_llinfo, M_TEMP, 0);
  757. rt->rt_llinfo = NULL;
  758. rt->rt_flags &= ~RTF_MPLS;
  759. }
  760. }
  761. #endif
  762. /* Hack to allow some flags to be toggled */
  763. if (rtm->rtm_fmask)
  764. rt->rt_flags =
  765. (rt->rt_flags & ~rtm->rtm_fmask) |
  766. (rtm->rtm_flags & rtm->rtm_fmask);
  767. rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
  768. &rt->rt_rmx);
  769. rtm->rtm_index = rt->rt_ifp->if_index;
  770. rtm->rtm_priority = rt->rt_priority & RTP_MASK;
  771. rtm->rtm_flags = rt->rt_flags;
  772. if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
  773. rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt);
  774. if (info.rti_info[RTAX_LABEL] != NULL) {
  775. char *rtlabel = ((struct sockaddr_rtlabel *)
  776. info.rti_info[RTAX_LABEL])->sr_label;
  777. rtlabel_unref(rt->rt_labelid);
  778. rt->rt_labelid =
  779. rtlabel_name2id(rtlabel);
  780. }
  781. if_group_routechange(info.rti_info[RTAX_DST],
  782. info.rti_info[RTAX_NETMASK]);
  783. /* FALLTHROUGH */
  784. case RTM_LOCK:
  785. rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
  786. rt->rt_rmx.rmx_locks |=
  787. (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
  788. rtm->rtm_priority = rt->rt_priority & RTP_MASK;
  789. break;
  790. }
  791. break;
  792. }
  793. flush:
  794. if (rtm) {
  795. if (error)
  796. rtm->rtm_errno = error;
  797. else {
  798. rtm->rtm_flags |= RTF_DONE;
  799. }
  800. }
  801. if (info.rti_info[RTAX_DST])
  802. route_proto.sp_protocol = info.rti_info[RTAX_DST]->sa_family;
  803. if (rt)
  804. rtfree(rt);
  805. /*
  806. * Check to see if we don't want our own messages.
  807. */
  808. if (!(so->so_options & SO_USELOOPBACK)) {
  809. if (route_cb.any_count <= 1) {
  810. fail:
  811. free(rtm, M_RTABLE, 0);
  812. m_freem(m);
  813. return (error);
  814. }
  815. /* There is another listener, so construct message */
  816. rp = sotorawcb(so);
  817. }
  818. if (rp)
  819. rp->rcb_proto.sp_family = 0; /* Avoid us */
  820. if (rtm) {
  821. if (m_copyback(m, 0, rtm->rtm_msglen, rtm, M_NOWAIT)) {
  822. m_freem(m);
  823. m = NULL;
  824. } else if (m->m_pkthdr.len > rtm->rtm_msglen)
  825. m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len);
  826. free(rtm, M_RTABLE, 0);
  827. }
  828. if (m)
  829. route_input(m, &route_proto, &route_src, &route_dst);
  830. if (rp)
  831. rp->rcb_proto.sp_family = PF_ROUTE;
  832. return (error);
  833. }
  834. void
  835. rt_setmetrics(u_long which, struct rt_metrics *in, struct rt_kmetrics *out)
  836. {
  837. if (which & RTV_MTU)
  838. out->rmx_mtu = in->rmx_mtu;
  839. if (which & RTV_EXPIRE)
  840. out->rmx_expire = in->rmx_expire;
  841. /* RTV_PRIORITY handled before */
  842. }
  843. void
  844. rt_getmetrics(struct rt_kmetrics *in, struct rt_metrics *out)
  845. {
  846. bzero(out, sizeof(*out));
  847. out->rmx_locks = in->rmx_locks;
  848. out->rmx_mtu = in->rmx_mtu;
  849. out->rmx_expire = in->rmx_expire;
  850. out->rmx_pksent = in->rmx_pksent;
  851. }
  852. #define ROUNDUP(a) \
  853. ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
  854. #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
  855. void
  856. rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo)
  857. {
  858. struct sockaddr *sa;
  859. int i;
  860. bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info));
  861. for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
  862. if ((rtinfo->rti_addrs & (1 << i)) == 0)
  863. continue;
  864. rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
  865. ADVANCE(cp, sa);
  866. }
  867. }
  868. struct mbuf *
  869. rt_msg1(int type, struct rt_addrinfo *rtinfo)
  870. {
  871. struct rt_msghdr *rtm;
  872. struct mbuf *m;
  873. int i;
  874. struct sockaddr *sa;
  875. int len, dlen, hlen;
  876. switch (type) {
  877. case RTM_DELADDR:
  878. case RTM_NEWADDR:
  879. len = sizeof(struct ifa_msghdr);
  880. break;
  881. case RTM_IFINFO:
  882. len = sizeof(struct if_msghdr);
  883. break;
  884. case RTM_IFANNOUNCE:
  885. len = sizeof(struct if_announcemsghdr);
  886. break;
  887. default:
  888. len = sizeof(struct rt_msghdr);
  889. break;
  890. }
  891. if (len > MCLBYTES)
  892. panic("rt_msg1");
  893. m = m_gethdr(M_DONTWAIT, MT_DATA);
  894. if (m && len > MHLEN) {
  895. MCLGET(m, M_DONTWAIT);
  896. if ((m->m_flags & M_EXT) == 0) {
  897. m_free(m);
  898. m = NULL;
  899. }
  900. }
  901. if (m == NULL)
  902. return (m);
  903. m->m_pkthdr.len = m->m_len = hlen = len;
  904. m->m_pkthdr.ph_ifidx = 0;
  905. rtm = mtod(m, struct rt_msghdr *);
  906. bzero(rtm, len);
  907. for (i = 0; i < RTAX_MAX; i++) {
  908. if (rtinfo == NULL || (sa = rtinfo->rti_info[i]) == NULL)
  909. continue;
  910. rtinfo->rti_addrs |= (1 << i);
  911. dlen = ROUNDUP(sa->sa_len);
  912. if (m_copyback(m, len, dlen, sa, M_NOWAIT)) {
  913. m_freem(m);
  914. return (NULL);
  915. }
  916. len += dlen;
  917. }
  918. rtm->rtm_msglen = len;
  919. rtm->rtm_hdrlen = hlen;
  920. rtm->rtm_version = RTM_VERSION;
  921. rtm->rtm_type = type;
  922. return (m);
  923. }
  924. int
  925. rt_msg2(int type, int vers, struct rt_addrinfo *rtinfo, caddr_t cp,
  926. struct walkarg *w)
  927. {
  928. int i;
  929. int len, dlen, hlen, second_time = 0;
  930. caddr_t cp0;
  931. rtinfo->rti_addrs = 0;
  932. again:
  933. switch (type) {
  934. case RTM_DELADDR:
  935. case RTM_NEWADDR:
  936. len = sizeof(struct ifa_msghdr);
  937. break;
  938. case RTM_IFINFO:
  939. len = sizeof(struct if_msghdr);
  940. break;
  941. default:
  942. len = sizeof(struct rt_msghdr);
  943. break;
  944. }
  945. hlen = len;
  946. if ((cp0 = cp) != NULL)
  947. cp += len;
  948. for (i = 0; i < RTAX_MAX; i++) {
  949. struct sockaddr *sa;
  950. if ((sa = rtinfo->rti_info[i]) == NULL)
  951. continue;
  952. rtinfo->rti_addrs |= (1 << i);
  953. dlen = ROUNDUP(sa->sa_len);
  954. if (cp) {
  955. bcopy(sa, cp, (size_t)dlen);
  956. cp += dlen;
  957. }
  958. len += dlen;
  959. }
  960. /* align message length to the next natural boundary */
  961. len = ALIGN(len);
  962. if (cp == 0 && w != NULL && !second_time) {
  963. struct walkarg *rw = w;
  964. rw->w_needed += len;
  965. if (rw->w_needed <= 0 && rw->w_where) {
  966. if (rw->w_tmemsize < len) {
  967. free(rw->w_tmem, M_RTABLE, 0);
  968. rw->w_tmem = malloc(len, M_RTABLE, M_NOWAIT);
  969. if (rw->w_tmem)
  970. rw->w_tmemsize = len;
  971. }
  972. if (rw->w_tmem) {
  973. cp = rw->w_tmem;
  974. second_time = 1;
  975. goto again;
  976. } else
  977. rw->w_where = 0;
  978. }
  979. }
  980. if (cp && w) /* clear the message header */
  981. bzero(cp0, hlen);
  982. if (cp) {
  983. struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
  984. rtm->rtm_version = RTM_VERSION;
  985. rtm->rtm_type = type;
  986. rtm->rtm_msglen = len;
  987. rtm->rtm_hdrlen = hlen;
  988. }
  989. return (len);
  990. }
  991. /*
  992. * This routine is called to generate a message from the routing
  993. * socket indicating that a redirect has occurred, a routing lookup
  994. * has failed, or that a protocol has detected timeouts to a particular
  995. * destination.
  996. */
  997. void
  998. rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags,
  999. struct ifnet *ifp, int error, u_int tableid)
  1000. {
  1001. struct rt_msghdr *rtm;
  1002. struct mbuf *m;
  1003. struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
  1004. if (route_cb.any_count == 0)
  1005. return;
  1006. m = rt_msg1(type, rtinfo);
  1007. if (m == NULL)
  1008. return;
  1009. rtm = mtod(m, struct rt_msghdr *);
  1010. rtm->rtm_flags = RTF_DONE | flags;
  1011. rtm->rtm_errno = error;
  1012. rtm->rtm_tableid = tableid;
  1013. rtm->rtm_addrs = rtinfo->rti_addrs;
  1014. if (ifp != NULL)
  1015. rtm->rtm_index = ifp->if_index;
  1016. if (sa == NULL)
  1017. route_proto.sp_protocol = 0;
  1018. else
  1019. route_proto.sp_protocol = sa->sa_family;
  1020. route_input(m, &route_proto, &route_src, &route_dst);
  1021. }
  1022. /*
  1023. * This routine is called to generate a message from the routing
  1024. * socket indicating that the status of a network interface has changed.
  1025. */
  1026. void
  1027. rt_ifmsg(struct ifnet *ifp)
  1028. {
  1029. struct if_msghdr *ifm;
  1030. struct mbuf *m;
  1031. if (route_cb.any_count == 0)
  1032. return;
  1033. m = rt_msg1(RTM_IFINFO, NULL);
  1034. if (m == NULL)
  1035. return;
  1036. ifm = mtod(m, struct if_msghdr *);
  1037. ifm->ifm_index = ifp->if_index;
  1038. ifm->ifm_tableid = ifp->if_rdomain;
  1039. ifm->ifm_flags = ifp->if_flags;
  1040. ifm->ifm_xflags = ifp->if_xflags;
  1041. ifm->ifm_data = ifp->if_data;
  1042. ifm->ifm_addrs = 0;
  1043. route_proto.sp_protocol = 0;
  1044. route_input(m, &route_proto, &route_src, &route_dst);
  1045. }
  1046. /*
  1047. * This is called to generate messages from the routing socket
  1048. * indicating a network interface has had addresses associated with it.
  1049. * if we ever reverse the logic and replace messages TO the routing
  1050. * socket indicate a request to configure interfaces, then it will
  1051. * be unnecessary as the routing socket will automatically generate
  1052. * copies of it.
  1053. */
  1054. void
  1055. rt_sendaddrmsg(struct rtentry *rt, int cmd)
  1056. {
  1057. struct ifaddr *ifa = rt->rt_ifa;
  1058. struct ifnet *ifp = ifa->ifa_ifp;
  1059. struct mbuf *m = NULL;
  1060. struct rt_addrinfo info;
  1061. struct ifa_msghdr *ifam;
  1062. if (route_cb.any_count == 0)
  1063. return;
  1064. memset(&info, 0, sizeof(info));
  1065. info.rti_info[RTAX_IFA] = ifa->ifa_addr;
  1066. info.rti_info[RTAX_IFP] = (struct sockaddr *)ifp->if_sadl;
  1067. info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
  1068. info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
  1069. if ((m = rt_msg1(cmd, &info)) == NULL)
  1070. return;
  1071. ifam = mtod(m, struct ifa_msghdr *);
  1072. ifam->ifam_index = ifp->if_index;
  1073. ifam->ifam_metric = ifa->ifa_metric;
  1074. ifam->ifam_flags = ifa->ifa_flags;
  1075. ifam->ifam_addrs = info.rti_addrs;
  1076. ifam->ifam_tableid = ifp->if_rdomain;
  1077. if (ifa->ifa_addr == NULL)
  1078. route_proto.sp_protocol = 0;
  1079. else
  1080. route_proto.sp_protocol = ifa->ifa_addr->sa_family;
  1081. route_input(m, &route_proto, &route_src, &route_dst);
  1082. }
  1083. /*
  1084. * This is called to generate routing socket messages indicating
  1085. * network interface arrival and departure.
  1086. */
  1087. void
  1088. rt_ifannouncemsg(struct ifnet *ifp, int what)
  1089. {
  1090. struct if_announcemsghdr *ifan;
  1091. struct mbuf *m;
  1092. if (route_cb.any_count == 0)
  1093. return;
  1094. m = rt_msg1(RTM_IFANNOUNCE, NULL);
  1095. if (m == NULL)
  1096. return;
  1097. ifan = mtod(m, struct if_announcemsghdr *);
  1098. ifan->ifan_index = ifp->if_index;
  1099. strlcpy(ifan->ifan_name, ifp->if_xname, sizeof(ifan->ifan_name));
  1100. ifan->ifan_what = what;
  1101. route_proto.sp_protocol = 0;
  1102. route_input(m, &route_proto, &route_src, &route_dst);
  1103. }
  1104. /*
  1105. * This is used in dumping the kernel table via sysctl().
  1106. */
  1107. int
  1108. sysctl_dumpentry(struct rtentry *rt, void *v, unsigned int id)
  1109. {
  1110. struct walkarg *w = v;
  1111. int error = 0, size;
  1112. struct rt_addrinfo info;
  1113. #ifdef MPLS
  1114. struct sockaddr_mpls sa_mpls;
  1115. #endif
  1116. struct sockaddr_rtlabel sa_rl;
  1117. if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
  1118. return 0;
  1119. if (w->w_op == NET_RT_DUMP && w->w_arg) {
  1120. u_int8_t prio = w->w_arg & RTP_MASK;
  1121. if (w->w_arg < 0) {
  1122. prio = (-w->w_arg) & RTP_MASK;
  1123. /* Show all routes that are not this priority */
  1124. if (prio == (rt->rt_priority & RTP_MASK))
  1125. return 0;
  1126. } else {
  1127. if (prio != (rt->rt_priority & RTP_MASK) &&
  1128. prio != RTP_ANY)
  1129. return 0;
  1130. }
  1131. }
  1132. bzero(&info, sizeof(info));
  1133. info.rti_info[RTAX_DST] = rt_key(rt);
  1134. info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
  1135. info.rti_info[RTAX_NETMASK] = rt_mask(rt);
  1136. if (rt->rt_ifp) {
  1137. info.rti_info[RTAX_IFP] =
  1138. (struct sockaddr *)rt->rt_ifp->if_sadl;
  1139. info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
  1140. if (rt->rt_ifp->if_flags & IFF_POINTOPOINT)
  1141. info.rti_info[RTAX_BRD] = rt->rt_ifa->ifa_dstaddr;
  1142. }
  1143. info.rti_info[RTAX_LABEL] = rtlabel_id2sa(rt->rt_labelid, &sa_rl);
  1144. #ifdef MPLS
  1145. if (rt->rt_flags & RTF_MPLS) {
  1146. bzero(&sa_mpls, sizeof(sa_mpls));
  1147. sa_mpls.smpls_family = AF_MPLS;
  1148. sa_mpls.smpls_len = sizeof(sa_mpls);
  1149. sa_mpls.smpls_label = ((struct rt_mpls *)
  1150. rt->rt_llinfo)->mpls_label;
  1151. info.rti_info[RTAX_SRC] = (struct sockaddr *)&sa_mpls;
  1152. info.rti_mpls = ((struct rt_mpls *)
  1153. rt->rt_llinfo)->mpls_operation;
  1154. }
  1155. #endif
  1156. size = rt_msg2(RTM_GET, RTM_VERSION, &info, NULL, w);
  1157. if (w->w_where && w->w_tmem && w->w_needed <= 0) {
  1158. struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
  1159. rtm->rtm_flags = rt->rt_flags;
  1160. rtm->rtm_priority = rt->rt_priority & RTP_MASK;
  1161. rt_getmetrics(&rt->rt_rmx, &rtm->rtm_rmx);
  1162. rtm->rtm_rmx.rmx_refcnt = rt->rt_refcnt;
  1163. rtm->rtm_index = rt->rt_ifp->if_index;
  1164. rtm->rtm_addrs = info.rti_addrs;
  1165. rtm->rtm_tableid = id;
  1166. #ifdef MPLS
  1167. rtm->rtm_mpls = info.rti_mpls;
  1168. #endif
  1169. if ((error = copyout(rtm, w->w_where, size)) != 0)
  1170. w->w_where = NULL;
  1171. else
  1172. w->w_where += size;
  1173. }
  1174. return (error);
  1175. }
  1176. int
  1177. sysctl_iflist(int af, struct walkarg *w)
  1178. {
  1179. struct ifnet *ifp;
  1180. struct ifaddr *ifa;
  1181. struct rt_addrinfo info;
  1182. int len, error = 0;
  1183. bzero(&info, sizeof(info));
  1184. TAILQ_FOREACH(ifp, &ifnet, if_list) {
  1185. if (w->w_arg && w->w_arg != ifp->if_index)
  1186. continue;
  1187. /* Copy the link-layer address first */
  1188. info.rti_info[RTAX_IFP] = (struct sockaddr *)ifp->if_sadl;
  1189. len = rt_msg2(RTM_IFINFO, RTM_VERSION, &info, 0, w);
  1190. if (w->w_where && w->w_tmem && w->w_needed <= 0) {
  1191. struct if_msghdr *ifm;
  1192. ifm = (struct if_msghdr *)w->w_tmem;
  1193. ifm->ifm_index = ifp->if_index;
  1194. ifm->ifm_tableid = ifp->if_rdomain;
  1195. ifm->ifm_flags = ifp->if_flags;
  1196. ifm->ifm_data = ifp->if_data;
  1197. ifm->ifm_addrs = info.rti_addrs;
  1198. error = copyout(ifm, w->w_where, len);
  1199. if (error)
  1200. return (error);
  1201. w->w_where += len;
  1202. }
  1203. info.rti_info[RTAX_IFP] = NULL;
  1204. TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
  1205. KASSERT(ifa->ifa_addr->sa_family != AF_LINK);
  1206. if (af && af != ifa->ifa_addr->sa_family)
  1207. continue;
  1208. info.rti_info[RTAX_IFA] = ifa->ifa_addr;
  1209. info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
  1210. info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
  1211. len = rt_msg2(RTM_NEWADDR, RTM_VERSION, &info, 0, w);
  1212. if (w->w_where && w->w_tmem && w->w_needed <= 0) {
  1213. struct ifa_msghdr *ifam;
  1214. ifam = (struct ifa_msghdr *)w->w_tmem;
  1215. ifam->ifam_index = ifa->ifa_ifp->if_index;
  1216. ifam->ifam_flags = ifa->ifa_flags;
  1217. ifam->ifam_metric = ifa->ifa_metric;
  1218. ifam->ifam_addrs = info.rti_addrs;
  1219. error = copyout(w->w_tmem, w->w_where, len);
  1220. if (error)
  1221. return (error);
  1222. w->w_where += len;
  1223. }
  1224. }
  1225. info.rti_info[RTAX_IFA] = info.rti_info[RTAX_NETMASK] =
  1226. info.rti_info[RTAX_BRD] = NULL;
  1227. }
  1228. return (0);
  1229. }
  1230. int
  1231. sysctl_rtable(int *name, u_int namelen, void *where, size_t *given, void *new,
  1232. size_t newlen)
  1233. {
  1234. int i, s, error = EINVAL;
  1235. u_char af;
  1236. struct walkarg w;
  1237. struct rt_tableinfo tableinfo;
  1238. u_int tableid = 0;
  1239. if (new)
  1240. return (EPERM);
  1241. if (namelen < 3 || namelen > 4)
  1242. return (EINVAL);
  1243. af = name[0];
  1244. bzero(&w, sizeof(w));
  1245. w.w_where = where;
  1246. w.w_given = *given;
  1247. w.w_needed = 0 - w.w_given;
  1248. w.w_op = name[1];
  1249. w.w_arg = name[2];
  1250. if (namelen == 4) {
  1251. tableid = name[3];
  1252. if (!rtable_exists(tableid))
  1253. return (ENOENT);
  1254. } else
  1255. tableid = curproc->p_p->ps_rtableid;
  1256. s = splsoftnet();
  1257. switch (w.w_op) {
  1258. case NET_RT_DUMP:
  1259. case NET_RT_FLAGS:
  1260. for (i = 1; i <= AF_MAX; i++) {
  1261. if (af != 0 && af != i)
  1262. continue;
  1263. error = rtable_walk(tableid, i, sysctl_dumpentry, &w);
  1264. if (error == EAFNOSUPPORT)
  1265. error = 0;
  1266. if (error)
  1267. break;
  1268. }
  1269. break;
  1270. case NET_RT_IFLIST:
  1271. error = sysctl_iflist(af, &w);
  1272. break;
  1273. case NET_RT_STATS:
  1274. error = sysctl_rdstruct(where, given, new,
  1275. &rtstat, sizeof(rtstat));
  1276. splx(s);
  1277. return (error);
  1278. case NET_RT_TABLE:
  1279. tableid = w.w_arg;
  1280. if (!rtable_exists(tableid)) {
  1281. splx(s);
  1282. return (ENOENT);
  1283. }
  1284. tableinfo.rti_tableid = tableid;
  1285. tableinfo.rti_domainid = rtable_l2(tableid);
  1286. error = sysctl_rdstruct(where, given, new,
  1287. &tableinfo, sizeof(tableinfo));
  1288. splx(s);
  1289. return (error);
  1290. }
  1291. splx(s);
  1292. free(w.w_tmem, M_RTABLE, 0);
  1293. w.w_needed += w.w_given;
  1294. if (where) {
  1295. *given = w.w_where - (caddr_t)where;
  1296. if (*given < w.w_needed)
  1297. return (ENOMEM);
  1298. } else
  1299. *given = (11 * w.w_needed) / 10;
  1300. return (error);
  1301. }
  1302. /*
  1303. * Definitions of protocols supported in the ROUTE domain.
  1304. */
  1305. extern struct domain routedomain; /* or at least forward */
  1306. struct protosw routesw[] = {
  1307. { SOCK_RAW, &routedomain, 0, PR_ATOMIC|PR_ADDR|PR_WANTRCVD,
  1308. route_input, route_output, raw_ctlinput, route_ctloutput,
  1309. route_usrreq,
  1310. raw_init, 0, 0, 0,
  1311. sysctl_rtable,
  1312. }
  1313. };
  1314. struct domain routedomain =
  1315. { PF_ROUTE, "route", route_init, 0, 0,
  1316. routesw, &routesw[nitems(routesw)] };