FreeBSD/Linux Kernel Cross Reference
sys/net/rtsock.c
1 /*-
2 * Copyright (c) 1988, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 4. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * @(#)rtsock.c 8.7 (Berkeley) 10/12/95
30 * $FreeBSD$
31 */
32 #include "opt_sctp.h"
33 #include "opt_inet.h"
34 #include "opt_inet6.h"
35
36 #include <sys/param.h>
37 #include <sys/domain.h>
38 #include <sys/jail.h>
39 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/mbuf.h>
42 #include <sys/priv.h>
43 #include <sys/proc.h>
44 #include <sys/protosw.h>
45 #include <sys/signalvar.h>
46 #include <sys/socket.h>
47 #include <sys/socketvar.h>
48 #include <sys/sysctl.h>
49 #include <sys/systm.h>
50
51 #include <net/if.h>
52 #include <net/netisr.h>
53 #include <net/raw_cb.h>
54 #include <net/route.h>
55
56 #include <netinet/in.h>
57 #ifdef INET6
58 #include <netinet6/scope6_var.h>
59 #endif
60
61 #ifdef SCTP
62 extern void sctp_addr_change(struct ifaddr *ifa, int cmd);
63 #endif /* SCTP */
64
65 #ifdef COMPAT_FREEBSD32
66 #include <sys/mount.h>
67 #include <compat/freebsd32/freebsd32.h>
68
69 struct if_data32 {
70 uint8_t ifi_type;
71 uint8_t ifi_physical;
72 uint8_t ifi_addrlen;
73 uint8_t ifi_hdrlen;
74 uint8_t ifi_link_state;
75 uint8_t ifi_spare_char1;
76 uint8_t ifi_spare_char2;
77 uint8_t ifi_datalen;
78 uint32_t ifi_mtu;
79 uint32_t ifi_metric;
80 uint32_t ifi_baudrate;
81 uint32_t ifi_ipackets;
82 uint32_t ifi_ierrors;
83 uint32_t ifi_opackets;
84 uint32_t ifi_oerrors;
85 uint32_t ifi_collisions;
86 uint32_t ifi_ibytes;
87 uint32_t ifi_obytes;
88 uint32_t ifi_imcasts;
89 uint32_t ifi_omcasts;
90 uint32_t ifi_iqdrops;
91 uint32_t ifi_noproto;
92 uint32_t ifi_hwassist;
93 int32_t ifi_epoch;
94 struct timeval32 ifi_lastchange;
95 };
96
97 struct if_msghdr32 {
98 uint16_t ifm_msglen;
99 uint8_t ifm_version;
100 uint8_t ifm_type;
101 int32_t ifm_addrs;
102 int32_t ifm_flags;
103 uint16_t ifm_index;
104 struct if_data32 ifm_data;
105 };
106
107 struct if_msghdrl32 {
108 uint16_t ifm_msglen;
109 uint8_t ifm_version;
110 uint8_t ifm_type;
111 int32_t ifm_addrs;
112 int32_t ifm_flags;
113 uint16_t ifm_index;
114 uint16_t _ifm_spare1;
115 uint16_t ifm_len;
116 uint16_t ifm_data_off;
117 struct if_data32 ifm_data;
118 };
119
120 struct ifa_msghdrl32 {
121 uint16_t ifam_msglen;
122 uint8_t ifam_version;
123 uint8_t ifam_type;
124 int32_t ifam_addrs;
125 int32_t ifam_flags;
126 uint16_t ifam_index;
127 uint16_t _ifam_spare1;
128 uint16_t ifam_len;
129 uint16_t ifam_data_off;
130 int32_t ifam_metric;
131 struct if_data32 ifam_data;
132 };
133 #endif /* COMPAT_FREEBSD32 */
134
135 MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables");
136
137 /* NB: these are not modified */
138 static struct sockaddr route_src = { 2, PF_ROUTE, };
139 static struct sockaddr sa_zero = { sizeof(sa_zero), AF_INET, };
140
141 /*
142 * Used by rtsock/raw_input callback code to decide whether to filter the update
143 * notification to a socket bound to a particular FIB.
144 */
145 #define RTS_FILTER_FIB M_PROTO8
146 #define RTS_ALLFIBS -1
147
148 static struct {
149 int ip_count; /* attached w/ AF_INET */
150 int ip6_count; /* attached w/ AF_INET6 */
151 int ipx_count; /* attached w/ AF_IPX */
152 int any_count; /* total attached */
153 } route_cb;
154
155 struct mtx rtsock_mtx;
156 MTX_SYSINIT(rtsock, &rtsock_mtx, "rtsock route_cb lock", MTX_DEF);
157
158 #define RTSOCK_LOCK() mtx_lock(&rtsock_mtx)
159 #define RTSOCK_UNLOCK() mtx_unlock(&rtsock_mtx)
160 #define RTSOCK_LOCK_ASSERT() mtx_assert(&rtsock_mtx, MA_OWNED)
161
162 static struct ifqueue rtsintrq;
163
164 SYSCTL_NODE(_net, OID_AUTO, route, CTLFLAG_RD, 0, "");
165 SYSCTL_INT(_net_route, OID_AUTO, netisr_maxqlen, CTLFLAG_RW,
166 &rtsintrq.ifq_maxlen, 0, "maximum routing socket dispatch queue length");
167
168 struct walkarg {
169 int w_tmemsize;
170 int w_op, w_arg;
171 caddr_t w_tmem;
172 struct sysctl_req *w_req;
173 };
174
175 static void rts_input(struct mbuf *m);
176 static struct mbuf *rt_msg1(int type, struct rt_addrinfo *rtinfo);
177 static int rt_msg2(int type, struct rt_addrinfo *rtinfo,
178 caddr_t cp, struct walkarg *w);
179 static int rt_xaddrs(caddr_t cp, caddr_t cplim,
180 struct rt_addrinfo *rtinfo);
181 static int sysctl_dumpentry(struct radix_node *rn, void *vw);
182 static int sysctl_iflist(int af, struct walkarg *w);
183 static int sysctl_ifmalist(int af, struct walkarg *w);
184 static int route_output(struct mbuf *m, struct socket *so);
185 static void rt_setmetrics(u_long which, const struct rt_metrics *in,
186 struct rt_metrics_lite *out);
187 static void rt_getmetrics(const struct rt_metrics_lite *in,
188 struct rt_metrics *out);
189 static void rt_dispatch(struct mbuf *, const struct sockaddr *);
190
191 static void
192 rts_init(void)
193 {
194 int tmp;
195
196 rtsintrq.ifq_maxlen = 256;
197 if (TUNABLE_INT_FETCH("net.route.netisr_maxqlen", &tmp))
198 rtsintrq.ifq_maxlen = tmp;
199 mtx_init(&rtsintrq.ifq_mtx, "rts_inq", NULL, MTX_DEF);
200 netisr_register(NETISR_ROUTE, rts_input, &rtsintrq, NETISR_MPSAFE);
201 }
202 SYSINIT(rtsock, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, rts_init, 0);
203
204 static int
205 raw_input_rts_cb(struct mbuf *m, struct sockproto *proto, struct sockaddr *src,
206 struct rawcb *rp)
207 {
208 int fibnum;
209
210 KASSERT(m != NULL, ("%s: m is NULL", __func__));
211 KASSERT(proto != NULL, ("%s: proto is NULL", __func__));
212 KASSERT(rp != NULL, ("%s: rp is NULL", __func__));
213
214 /* No filtering requested. */
215 if ((m->m_flags & RTS_FILTER_FIB) == 0)
216 return (0);
217
218 /* Check if it is a rts and the fib matches the one of the socket. */
219 fibnum = M_GETFIB(m);
220 if (proto->sp_family != PF_ROUTE ||
221 rp->rcb_socket == NULL ||
222 rp->rcb_socket->so_fibnum == fibnum)
223 return (0);
224
225 /* Filtering requested and no match, the socket shall be skipped. */
226 return (1);
227 }
228
229 static void
230 rts_input(struct mbuf *m)
231 {
232 struct sockproto route_proto;
233 unsigned short *family;
234 struct m_tag *tag;
235
236 route_proto.sp_family = PF_ROUTE;
237 tag = m_tag_find(m, PACKET_TAG_RTSOCKFAM, NULL);
238 if (tag != NULL) {
239 family = (unsigned short *)(tag + 1);
240 route_proto.sp_protocol = *family;
241 m_tag_delete(m, tag);
242 } else
243 route_proto.sp_protocol = 0;
244
245 raw_input_ext(m, &route_proto, &route_src, raw_input_rts_cb);
246 }
247
248 /*
249 * It really doesn't make any sense at all for this code to share much
250 * with raw_usrreq.c, since its functionality is so restricted. XXX
251 */
252 static void
253 rts_abort(struct socket *so)
254 {
255
256 raw_usrreqs.pru_abort(so);
257 }
258
259 static void
260 rts_close(struct socket *so)
261 {
262
263 raw_usrreqs.pru_close(so);
264 }
265
266 /* pru_accept is EOPNOTSUPP */
267
268 static int
269 rts_attach(struct socket *so, int proto, struct thread *td)
270 {
271 struct rawcb *rp;
272 int s, error;
273
274 KASSERT(so->so_pcb == NULL, ("rts_attach: so_pcb != NULL"));
275
276 /* XXX */
277 MALLOC(rp, struct rawcb *, sizeof *rp, M_PCB, M_WAITOK | M_ZERO);
278 if (rp == NULL)
279 return ENOBUFS;
280
281 /*
282 * The splnet() is necessary to block protocols from sending
283 * error notifications (like RTM_REDIRECT or RTM_LOSING) while
284 * this PCB is extant but incompletely initialized.
285 * Probably we should try to do more of this work beforehand and
286 * eliminate the spl.
287 */
288 s = splnet();
289 so->so_pcb = (caddr_t)rp;
290 so->so_fibnum = td->td_proc->p_fibnum;
291 error = raw_attach(so, proto);
292 rp = sotorawcb(so);
293 if (error) {
294 splx(s);
295 so->so_pcb = NULL;
296 free(rp, M_PCB);
297 return error;
298 }
299 RTSOCK_LOCK();
300 switch(rp->rcb_proto.sp_protocol) {
301 case AF_INET:
302 route_cb.ip_count++;
303 break;
304 case AF_INET6:
305 route_cb.ip6_count++;
306 break;
307 case AF_IPX:
308 route_cb.ipx_count++;
309 break;
310 }
311 route_cb.any_count++;
312 RTSOCK_UNLOCK();
313 soisconnected(so);
314 so->so_options |= SO_USELOOPBACK;
315 splx(s);
316 return 0;
317 }
318
319 static int
320 rts_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
321 {
322
323 return (raw_usrreqs.pru_bind(so, nam, td)); /* xxx just EINVAL */
324 }
325
326 static int
327 rts_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
328 {
329
330 return (raw_usrreqs.pru_connect(so, nam, td)); /* XXX just EINVAL */
331 }
332
333 /* pru_connect2 is EOPNOTSUPP */
334 /* pru_control is EOPNOTSUPP */
335
336 static void
337 rts_detach(struct socket *so)
338 {
339 struct rawcb *rp = sotorawcb(so);
340
341 KASSERT(rp != NULL, ("rts_detach: rp == NULL"));
342
343 RTSOCK_LOCK();
344 switch(rp->rcb_proto.sp_protocol) {
345 case AF_INET:
346 route_cb.ip_count--;
347 break;
348 case AF_INET6:
349 route_cb.ip6_count--;
350 break;
351 case AF_IPX:
352 route_cb.ipx_count--;
353 break;
354 }
355 route_cb.any_count--;
356 RTSOCK_UNLOCK();
357 raw_usrreqs.pru_detach(so);
358 }
359
360 static int
361 rts_disconnect(struct socket *so)
362 {
363
364 return (raw_usrreqs.pru_disconnect(so));
365 }
366
367 /* pru_listen is EOPNOTSUPP */
368
369 static int
370 rts_peeraddr(struct socket *so, struct sockaddr **nam)
371 {
372
373 return (raw_usrreqs.pru_peeraddr(so, nam));
374 }
375
376 /* pru_rcvd is EOPNOTSUPP */
377 /* pru_rcvoob is EOPNOTSUPP */
378
379 static int
380 rts_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
381 struct mbuf *control, struct thread *td)
382 {
383
384 return (raw_usrreqs.pru_send(so, flags, m, nam, control, td));
385 }
386
387 /* pru_sense is null */
388
389 static int
390 rts_shutdown(struct socket *so)
391 {
392
393 return (raw_usrreqs.pru_shutdown(so));
394 }
395
396 static int
397 rts_sockaddr(struct socket *so, struct sockaddr **nam)
398 {
399
400 return (raw_usrreqs.pru_sockaddr(so, nam));
401 }
402
403 static struct pr_usrreqs route_usrreqs = {
404 .pru_abort = rts_abort,
405 .pru_attach = rts_attach,
406 .pru_bind = rts_bind,
407 .pru_connect = rts_connect,
408 .pru_detach = rts_detach,
409 .pru_disconnect = rts_disconnect,
410 .pru_peeraddr = rts_peeraddr,
411 .pru_send = rts_send,
412 .pru_shutdown = rts_shutdown,
413 .pru_sockaddr = rts_sockaddr,
414 .pru_close = rts_close,
415 };
416
417 #ifndef _SOCKADDR_UNION_DEFINED
418 #define _SOCKADDR_UNION_DEFINED
419 /*
420 * The union of all possible address formats we handle.
421 */
422 union sockaddr_union {
423 struct sockaddr sa;
424 struct sockaddr_in sin;
425 struct sockaddr_in6 sin6;
426 };
427 #endif /* _SOCKADDR_UNION_DEFINED */
428
429 static int
430 rtm_get_jailed(struct rt_addrinfo *info, struct ifnet *ifp,
431 struct rtentry *rt, union sockaddr_union *saun, struct ucred *cred)
432 {
433
434 /* First, see if the returned address is part of the jail. */
435 if (prison_if(cred, rt->rt_ifa->ifa_addr) == 0) {
436 info->rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
437 return (0);
438 }
439
440 switch (info->rti_info[RTAX_DST]->sa_family) {
441 #ifdef INET
442 case AF_INET:
443 {
444 struct in_addr ia;
445 struct ifaddr *ifa;
446 int found;
447
448 found = 0;
449 /*
450 * Try to find an address on the given outgoing interface
451 * that belongs to the jail.
452 */
453 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
454 struct sockaddr *sa;
455 sa = ifa->ifa_addr;
456 if (sa->sa_family != AF_INET)
457 continue;
458 ia = ((struct sockaddr_in *)sa)->sin_addr;
459 if (prison_check_ip4(cred, &ia) == 0) {
460 found = 1;
461 break;
462 }
463 }
464 if (!found) {
465 /*
466 * As a last resort return the 'default' jail address.
467 */
468 if (prison_get_ip4(cred, &ia) != 0)
469 return (ESRCH);
470 }
471 bzero(&saun->sin, sizeof(struct sockaddr_in));
472 saun->sin.sin_len = sizeof(struct sockaddr_in);
473 saun->sin.sin_family = AF_INET;
474 saun->sin.sin_addr.s_addr = ia.s_addr;
475 info->rti_info[RTAX_IFA] = (struct sockaddr *)&saun->sin;
476 break;
477 }
478 #endif
479 #ifdef INET6
480 case AF_INET6:
481 {
482 struct in6_addr ia6;
483 struct ifaddr *ifa;
484 int found;
485
486 found = 0;
487 /*
488 * Try to find an address on the given outgoing interface
489 * that belongs to the jail.
490 */
491 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
492 struct sockaddr *sa;
493 sa = ifa->ifa_addr;
494 if (sa->sa_family != AF_INET6)
495 continue;
496 bcopy(&((struct sockaddr_in6 *)sa)->sin6_addr,
497 &ia6, sizeof(struct in6_addr));
498 if (prison_check_ip6(cred, &ia6) == 0) {
499 found = 1;
500 break;
501 }
502 }
503 if (!found) {
504 /*
505 * As a last resort return the 'default' jail address.
506 */
507 if (prison_get_ip6(cred, &ia6) != 0)
508 return (ESRCH);
509 }
510 bzero(&saun->sin6, sizeof(struct sockaddr_in6));
511 saun->sin6.sin6_len = sizeof(struct sockaddr_in6);
512 saun->sin6.sin6_family = AF_INET6;
513 bcopy(&ia6, &saun->sin6.sin6_addr, sizeof(struct in6_addr));
514 if (sa6_recoverscope(&saun->sin6) != 0)
515 return (ESRCH);
516 info->rti_info[RTAX_IFA] = (struct sockaddr *)&saun->sin6;
517 break;
518 }
519 #endif
520 default:
521 return (ESRCH);
522 }
523 return (0);
524 }
525
526 /*ARGSUSED*/
527 static int
528 route_output(struct mbuf *m, struct socket *so)
529 {
530 #define sa_equal(a1, a2) (bcmp((a1), (a2), (a1)->sa_len) == 0)
531 struct rt_msghdr *rtm = NULL;
532 struct rtentry *rt = NULL;
533 struct radix_node_head *rnh;
534 struct rt_addrinfo info;
535 int len, error = 0;
536 struct ifnet *ifp = NULL;
537 union sockaddr_union saun;
538
539 #define senderr(e) { error = e; goto flush;}
540 if (m == NULL || ((m->m_len < sizeof(long)) &&
541 (m = m_pullup(m, sizeof(long))) == NULL))
542 return (ENOBUFS);
543 if ((m->m_flags & M_PKTHDR) == 0)
544 panic("route_output");
545 len = m->m_pkthdr.len;
546 if (len < sizeof(*rtm) ||
547 len != mtod(m, struct rt_msghdr *)->rtm_msglen) {
548 info.rti_info[RTAX_DST] = NULL;
549 senderr(EINVAL);
550 }
551 R_Malloc(rtm, struct rt_msghdr *, len);
552 if (rtm == NULL) {
553 info.rti_info[RTAX_DST] = NULL;
554 senderr(ENOBUFS);
555 }
556 m_copydata(m, 0, len, (caddr_t)rtm);
557 if (rtm->rtm_version != RTM_VERSION) {
558 info.rti_info[RTAX_DST] = NULL;
559 senderr(EPROTONOSUPPORT);
560 }
561 rtm->rtm_pid = curproc->p_pid;
562 bzero(&info, sizeof(info));
563 info.rti_addrs = rtm->rtm_addrs;
564 if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info)) {
565 info.rti_info[RTAX_DST] = NULL;
566 senderr(EINVAL);
567 }
568 info.rti_flags = rtm->rtm_flags;
569 if (info.rti_info[RTAX_DST] == NULL ||
570 info.rti_info[RTAX_DST]->sa_family >= AF_MAX ||
571 (info.rti_info[RTAX_GATEWAY] != NULL &&
572 info.rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX))
573 senderr(EINVAL);
574 if (info.rti_info[RTAX_GENMASK]) {
575 struct radix_node *t;
576 t = rn_addmask((caddr_t) info.rti_info[RTAX_GENMASK], 0, 1);
577 if (t != NULL &&
578 bcmp((char *)(void *)info.rti_info[RTAX_GENMASK] + 1,
579 (char *)(void *)t->rn_key + 1,
580 ((struct sockaddr *)t->rn_key)->sa_len - 1) == 0)
581 info.rti_info[RTAX_GENMASK] =
582 (struct sockaddr *)t->rn_key;
583 else
584 senderr(ENOBUFS);
585 }
586
587 /*
588 * Verify that the caller has the appropriate privilege; RTM_GET
589 * is the only operation the non-superuser is allowed.
590 */
591 if (rtm->rtm_type != RTM_GET) {
592 error = priv_check(curthread, PRIV_NET_ROUTE);
593 if (error)
594 senderr(error);
595 }
596
597 switch (rtm->rtm_type) {
598 struct rtentry *saved_nrt;
599
600 case RTM_ADD:
601 if (info.rti_info[RTAX_GATEWAY] == NULL)
602 senderr(EINVAL);
603 saved_nrt = NULL;
604 error = rtrequest1_fib(RTM_ADD, &info, &saved_nrt,
605 so->so_fibnum);
606 if (error == 0 && saved_nrt) {
607 RT_LOCK(saved_nrt);
608 rt_setmetrics(rtm->rtm_inits,
609 &rtm->rtm_rmx, &saved_nrt->rt_rmx);
610 rtm->rtm_index = saved_nrt->rt_ifp->if_index;
611 RT_REMREF(saved_nrt);
612 saved_nrt->rt_genmask = info.rti_info[RTAX_GENMASK];
613 RT_UNLOCK(saved_nrt);
614 }
615 break;
616
617 case RTM_DELETE:
618 saved_nrt = NULL;
619 error = rtrequest1_fib(RTM_DELETE, &info, &saved_nrt,
620 so->so_fibnum);
621 if (error == 0) {
622 RT_LOCK(saved_nrt);
623 rt = saved_nrt;
624 goto report;
625 }
626 break;
627
628 case RTM_GET:
629 case RTM_CHANGE:
630 case RTM_LOCK:
631 rnh = rt_tables[so->so_fibnum][info.rti_info[RTAX_DST]->sa_family];
632 if (rnh == NULL)
633 senderr(EAFNOSUPPORT);
634 RADIX_NODE_HEAD_LOCK(rnh);
635 rt = (struct rtentry *) rnh->rnh_lookup(info.rti_info[RTAX_DST],
636 info.rti_info[RTAX_NETMASK], rnh);
637 if (rt == NULL) { /* XXX looks bogus */
638 RADIX_NODE_HEAD_UNLOCK(rnh);
639 senderr(ESRCH);
640 }
641 RT_LOCK(rt);
642 RT_ADDREF(rt);
643 RADIX_NODE_HEAD_UNLOCK(rnh);
644
645 /*
646 * Fix for PR: 82974
647 *
648 * RTM_CHANGE/LOCK need a perfect match, rn_lookup()
649 * returns a perfect match in case a netmask is
650 * specified. For host routes only a longest prefix
651 * match is returned so it is necessary to compare the
652 * existence of the netmask. If both have a netmask
653 * rnh_lookup() did a perfect match and if none of them
654 * have a netmask both are host routes which is also a
655 * perfect match.
656 */
657
658 if (rtm->rtm_type != RTM_GET &&
659 (!rt_mask(rt) != !info.rti_info[RTAX_NETMASK])) {
660 RT_UNLOCK(rt);
661 senderr(ESRCH);
662 }
663
664 switch(rtm->rtm_type) {
665
666 case RTM_GET:
667 report:
668 RT_LOCK_ASSERT(rt);
669 if ((rt->rt_flags & RTF_HOST) == 0
670 ? jailed(curthread->td_ucred)
671 : prison_if(curthread->td_ucred,
672 rt_key(rt)) != 0) {
673 RT_UNLOCK(rt);
674 senderr(ESRCH);
675 }
676 info.rti_info[RTAX_DST] = rt_key(rt);
677 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
678 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
679 info.rti_info[RTAX_GENMASK] = rt->rt_genmask;
680 if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
681 ifp = rt->rt_ifp;
682 if (ifp) {
683 info.rti_info[RTAX_IFP] =
684 ifp->if_addr->ifa_addr;
685 error = rtm_get_jailed(&info, ifp, rt,
686 &saun, curthread->td_ucred);
687 if (error != 0) {
688 RT_UNLOCK(rt);
689 senderr(error);
690 }
691 if (ifp->if_flags & IFF_POINTOPOINT)
692 info.rti_info[RTAX_BRD] =
693 rt->rt_ifa->ifa_dstaddr;
694 rtm->rtm_index = ifp->if_index;
695 } else {
696 info.rti_info[RTAX_IFP] = NULL;
697 info.rti_info[RTAX_IFA] = NULL;
698 }
699 } else if ((ifp = rt->rt_ifp) != NULL) {
700 rtm->rtm_index = ifp->if_index;
701 }
702 len = rt_msg2(rtm->rtm_type, &info, NULL, NULL);
703 if (len > rtm->rtm_msglen) {
704 struct rt_msghdr *new_rtm;
705 R_Malloc(new_rtm, struct rt_msghdr *, len);
706 if (new_rtm == NULL) {
707 RT_UNLOCK(rt);
708 senderr(ENOBUFS);
709 }
710 bcopy(rtm, new_rtm, rtm->rtm_msglen);
711 Free(rtm); rtm = new_rtm;
712 }
713 (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm, NULL);
714 rtm->rtm_flags = rt->rt_flags;
715 rtm->rtm_use = 0;
716 rt_getmetrics(&rt->rt_rmx, &rtm->rtm_rmx);
717 rtm->rtm_addrs = info.rti_addrs;
718 break;
719
720 case RTM_CHANGE:
721 /*
722 * New gateway could require new ifaddr, ifp;
723 * flags may also be different; ifp may be specified
724 * by ll sockaddr when protocol address is ambiguous
725 */
726 if (((rt->rt_flags & RTF_GATEWAY) &&
727 info.rti_info[RTAX_GATEWAY] != NULL) ||
728 info.rti_info[RTAX_IFP] != NULL ||
729 (info.rti_info[RTAX_IFA] != NULL &&
730 !sa_equal(info.rti_info[RTAX_IFA],
731 rt->rt_ifa->ifa_addr))) {
732 RT_UNLOCK(rt);
733 RADIX_NODE_HEAD_LOCK(rnh);
734 error = rt_getifa_fib(&info, rt->rt_fibnum);
735 RADIX_NODE_HEAD_UNLOCK(rnh);
736 if (error != 0)
737 senderr(error);
738 RT_LOCK(rt);
739 }
740 if (info.rti_ifa != NULL &&
741 info.rti_ifa != rt->rt_ifa &&
742 rt->rt_ifa != NULL &&
743 rt->rt_ifa->ifa_rtrequest != NULL) {
744 rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt,
745 &info);
746 IFAFREE(rt->rt_ifa);
747 }
748 if (info.rti_info[RTAX_GATEWAY] != NULL) {
749 RT_UNLOCK(rt);
750 RADIX_NODE_HEAD_LOCK(rnh);
751 RT_LOCK(rt);
752
753 error = rt_setgate(rt, rt_key(rt),
754 info.rti_info[RTAX_GATEWAY]);
755 RADIX_NODE_HEAD_UNLOCK(rnh);
756 if (error != 0) {
757 RT_UNLOCK(rt);
758 senderr(error);
759 }
760 if (!(rt->rt_flags & RTF_LLINFO))
761 rt->rt_flags |= RTF_GATEWAY;
762 }
763 if (info.rti_ifa != NULL &&
764 info.rti_ifa != rt->rt_ifa) {
765 IFAREF(info.rti_ifa);
766 rt->rt_ifa = info.rti_ifa;
767 rt->rt_ifp = info.rti_ifp;
768 }
769 /* Allow some flags to be toggled on change. */
770 if (rtm->rtm_fmask & RTF_FMASK)
771 rt->rt_flags = (rt->rt_flags &
772 ~rtm->rtm_fmask) |
773 (rtm->rtm_flags & rtm->rtm_fmask);
774 rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
775 &rt->rt_rmx);
776 rtm->rtm_index = rt->rt_ifp->if_index;
777 if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) {
778 RT_UNLOCK(rt);
779 RADIX_NODE_HEAD_LOCK(rnh);
780 RT_LOCK(rt);
781 rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, &info);
782 RADIX_NODE_HEAD_UNLOCK(rnh);
783 }
784 if (info.rti_info[RTAX_GENMASK])
785 rt->rt_genmask = info.rti_info[RTAX_GENMASK];
786 /* FALLTHROUGH */
787 case RTM_LOCK:
788 /* We don't support locks anymore */
789 break;
790 }
791 RT_UNLOCK(rt);
792 break;
793
794 default:
795 senderr(EOPNOTSUPP);
796 }
797
798 flush:
799 if (rtm) {
800 if (error)
801 rtm->rtm_errno = error;
802 else
803 rtm->rtm_flags |= RTF_DONE;
804 }
805 if (rt) /* XXX can this be true? */
806 RTFREE(rt);
807 {
808 struct rawcb *rp = NULL;
809 /*
810 * Check to see if we don't want our own messages.
811 */
812 if ((so->so_options & SO_USELOOPBACK) == 0) {
813 if (route_cb.any_count <= 1) {
814 if (rtm)
815 Free(rtm);
816 m_freem(m);
817 return (error);
818 }
819 /* There is another listener, so construct message */
820 rp = sotorawcb(so);
821 }
822 if (rtm) {
823 m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
824 if (m->m_pkthdr.len < rtm->rtm_msglen) {
825 m_freem(m);
826 m = NULL;
827 } else if (m->m_pkthdr.len > rtm->rtm_msglen)
828 m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len);
829 Free(rtm);
830 }
831 if (m) {
832 M_SETFIB(m, so->so_fibnum);
833 m->m_flags |= RTS_FILTER_FIB;
834 if (rp) {
835 /*
836 * XXX insure we don't get a copy by
837 * invalidating our protocol
838 */
839 unsigned short family = rp->rcb_proto.sp_family;
840 rp->rcb_proto.sp_family = 0;
841 rt_dispatch(m, info.rti_info[RTAX_DST]);
842 rp->rcb_proto.sp_family = family;
843 } else
844 rt_dispatch(m, info.rti_info[RTAX_DST]);
845 }
846 }
847 return (error);
848 #undef sa_equal
849 }
850
851 static void
852 rt_setmetrics(u_long which, const struct rt_metrics *in,
853 struct rt_metrics_lite *out)
854 {
855 #define metric(f, e) if (which & (f)) out->e = in->e;
856 /*
857 * Only these are stored in the routing entry since introduction
858 * of tcp hostcache. The rest is ignored.
859 */
860 metric(RTV_MTU, rmx_mtu);
861 /* Userland -> kernel timebase conversion. */
862 if (which & RTV_EXPIRE)
863 out->rmx_expire = in->rmx_expire ?
864 in->rmx_expire - time_second + time_uptime : 0;
865 #undef metric
866 }
867
868 static void
869 rt_getmetrics(const struct rt_metrics_lite *in, struct rt_metrics *out)
870 {
871 #define metric(e) out->e = in->e;
872 bzero(out, sizeof(*out));
873 metric(rmx_mtu);
874 /* Kernel -> userland timebase conversion. */
875 out->rmx_expire = in->rmx_expire ?
876 in->rmx_expire - time_uptime + time_second : 0;
877 #undef metric
878 }
879
880 /*
881 * Extract the addresses of the passed sockaddrs.
882 * Do a little sanity checking so as to avoid bad memory references.
883 * This data is derived straight from userland.
884 */
885 static int
886 rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo)
887 {
888 struct sockaddr *sa;
889 int i;
890
891 for (i = 0; i < RTAX_MAX && cp < cplim; i++) {
892 if ((rtinfo->rti_addrs & (1 << i)) == 0)
893 continue;
894 sa = (struct sockaddr *)cp;
895 /*
896 * It won't fit.
897 */
898 if (cp + sa->sa_len > cplim)
899 return (EINVAL);
900 /*
901 * there are no more.. quit now
902 * If there are more bits, they are in error.
903 * I've seen this. route(1) can evidently generate these.
904 * This causes kernel to core dump.
905 * for compatibility, If we see this, point to a safe address.
906 */
907 if (sa->sa_len == 0) {
908 rtinfo->rti_info[i] = &sa_zero;
909 return (0); /* should be EINVAL but for compat */
910 }
911 /* accept it */
912 rtinfo->rti_info[i] = sa;
913 cp += SA_SIZE(sa);
914 }
915 return (0);
916 }
917
918 /*
919 * Used by the routing socket.
920 */
921 static struct mbuf *
922 rt_msg1(int type, struct rt_addrinfo *rtinfo)
923 {
924 struct rt_msghdr *rtm;
925 struct mbuf *m;
926 int i;
927 struct sockaddr *sa;
928 int len, dlen;
929
930 switch (type) {
931
932 case RTM_DELADDR:
933 case RTM_NEWADDR:
934 len = sizeof(struct ifa_msghdr);
935 break;
936
937 case RTM_DELMADDR:
938 case RTM_NEWMADDR:
939 len = sizeof(struct ifma_msghdr);
940 break;
941
942 case RTM_IFINFO:
943 len = sizeof(struct if_msghdr);
944 break;
945
946 case RTM_IFANNOUNCE:
947 case RTM_IEEE80211:
948 len = sizeof(struct if_announcemsghdr);
949 break;
950
951 default:
952 len = sizeof(struct rt_msghdr);
953 }
954 if (len > MCLBYTES)
955 panic("rt_msg1");
956 m = m_gethdr(M_DONTWAIT, MT_DATA);
957 if (m && len > MHLEN) {
958 MCLGET(m, M_DONTWAIT);
959 if ((m->m_flags & M_EXT) == 0) {
960 m_free(m);
961 m = NULL;
962 }
963 }
964 if (m == NULL)
965 return (m);
966 m->m_pkthdr.len = m->m_len = len;
967 m->m_pkthdr.rcvif = NULL;
968 rtm = mtod(m, struct rt_msghdr *);
969 bzero((caddr_t)rtm, len);
970 for (i = 0; i < RTAX_MAX; i++) {
971 if ((sa = rtinfo->rti_info[i]) == NULL)
972 continue;
973 rtinfo->rti_addrs |= (1 << i);
974 dlen = SA_SIZE(sa);
975 m_copyback(m, len, dlen, (caddr_t)sa);
976 len += dlen;
977 }
978 if (m->m_pkthdr.len != len) {
979 m_freem(m);
980 return (NULL);
981 }
982 rtm->rtm_msglen = len;
983 rtm->rtm_version = RTM_VERSION;
984 rtm->rtm_type = type;
985 return (m);
986 }
987
988 /*
989 * Used by the sysctl code and routing socket.
990 */
991 static int
992 rt_msg2(int type, struct rt_addrinfo *rtinfo, caddr_t cp, struct walkarg *w)
993 {
994 int i;
995 int len, dlen, second_time = 0;
996 caddr_t cp0;
997
998 rtinfo->rti_addrs = 0;
999 again:
1000 switch (type) {
1001
1002 case RTM_DELADDR:
1003 case RTM_NEWADDR:
1004 if (w != NULL && w->w_op == NET_RT_IFLISTL) {
1005 #ifdef COMPAT_FREEBSD32
1006 if (w->w_req->flags & SCTL_MASK32)
1007 len = sizeof(struct ifa_msghdrl32);
1008 else
1009 #endif
1010 len = sizeof(struct ifa_msghdrl);
1011 } else
1012 len = sizeof(struct ifa_msghdr);
1013 break;
1014
1015 case RTM_IFINFO:
1016 #ifdef COMPAT_FREEBSD32
1017 if (w != NULL && w->w_req->flags & SCTL_MASK32) {
1018 if (w->w_op == NET_RT_IFLISTL)
1019 len = sizeof(struct if_msghdrl32);
1020 else
1021 len = sizeof(struct if_msghdr32);
1022 break;
1023 }
1024 #endif
1025 if (w != NULL && w->w_op == NET_RT_IFLISTL)
1026 len = sizeof(struct if_msghdrl);
1027 else
1028 len = sizeof(struct if_msghdr);
1029 break;
1030
1031 case RTM_NEWMADDR:
1032 len = sizeof(struct ifma_msghdr);
1033 break;
1034
1035 default:
1036 len = sizeof(struct rt_msghdr);
1037 }
1038 cp0 = cp;
1039 if (cp0)
1040 cp += len;
1041 for (i = 0; i < RTAX_MAX; i++) {
1042 struct sockaddr *sa;
1043
1044 if ((sa = rtinfo->rti_info[i]) == NULL)
1045 continue;
1046 rtinfo->rti_addrs |= (1 << i);
1047 dlen = SA_SIZE(sa);
1048 if (cp) {
1049 bcopy((caddr_t)sa, cp, (unsigned)dlen);
1050 cp += dlen;
1051 }
1052 len += dlen;
1053 }
1054 len = ALIGN(len);
1055 if (cp == NULL && w != NULL && !second_time) {
1056 struct walkarg *rw = w;
1057
1058 if (rw->w_req) {
1059 if (rw->w_tmemsize < len) {
1060 if (rw->w_tmem)
1061 free(rw->w_tmem, M_RTABLE);
1062 rw->w_tmem = (caddr_t)
1063 malloc(len, M_RTABLE, M_NOWAIT);
1064 if (rw->w_tmem)
1065 rw->w_tmemsize = len;
1066 }
1067 if (rw->w_tmem) {
1068 cp = rw->w_tmem;
1069 second_time = 1;
1070 goto again;
1071 }
1072 }
1073 }
1074 if (cp) {
1075 struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
1076
1077 rtm->rtm_version = RTM_VERSION;
1078 rtm->rtm_type = type;
1079 rtm->rtm_msglen = len;
1080 }
1081 return (len);
1082 }
1083
1084 /*
1085 * This routine is called to generate a message from the routing
1086 * socket indicating that a redirect has occured, a routing lookup
1087 * has failed, or that a protocol has detected timeouts to a particular
1088 * destination.
1089 */
1090 void
1091 rt_missmsg_fib(int type, struct rt_addrinfo *rtinfo, int flags, int error,
1092 int fibnum)
1093 {
1094 struct rt_msghdr *rtm;
1095 struct mbuf *m;
1096 struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
1097
1098 if (route_cb.any_count == 0)
1099 return;
1100 m = rt_msg1(type, rtinfo);
1101 if (m == NULL)
1102 return;
1103
1104 if (fibnum != RTS_ALLFIBS) {
1105 KASSERT(fibnum >= 0 && fibnum < rt_numfibs, ("%s: fibnum out "
1106 "of range 0 <= %d < %d", __func__, fibnum, rt_numfibs));
1107 M_SETFIB(m, fibnum);
1108 m->m_flags |= RTS_FILTER_FIB;
1109 }
1110
1111 rtm = mtod(m, struct rt_msghdr *);
1112 rtm->rtm_flags = RTF_DONE | flags;
1113 rtm->rtm_errno = error;
1114 rtm->rtm_addrs = rtinfo->rti_addrs;
1115 rt_dispatch(m, sa);
1116 }
1117
1118 void
1119 rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error)
1120 {
1121
1122 rt_missmsg_fib(type, rtinfo, flags, error, RTS_ALLFIBS);
1123 }
1124
1125 /*
1126 * This routine is called to generate a message from the routing
1127 * socket indicating that the status of a network interface has changed.
1128 */
1129 void
1130 rt_ifmsg(struct ifnet *ifp)
1131 {
1132 struct if_msghdr *ifm;
1133 struct mbuf *m;
1134 struct rt_addrinfo info;
1135
1136 if (route_cb.any_count == 0)
1137 return;
1138 bzero((caddr_t)&info, sizeof(info));
1139 m = rt_msg1(RTM_IFINFO, &info);
1140 if (m == NULL)
1141 return;
1142 ifm = mtod(m, struct if_msghdr *);
1143 ifm->ifm_index = ifp->if_index;
1144 ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
1145 ifm->ifm_data = ifp->if_data;
1146 ifm->ifm_addrs = 0;
1147 rt_dispatch(m, NULL);
1148 }
1149
1150 /*
1151 * This is called to generate messages from the routing socket
1152 * indicating a network interface has had addresses associated with it.
1153 * if we ever reverse the logic and replace messages TO the routing
1154 * socket indicate a request to configure interfaces, then it will
1155 * be unnecessary as the routing socket will automatically generate
1156 * copies of it.
1157 */
1158 void
1159 rt_newaddrmsg_fib(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt,
1160 int fibnum)
1161 {
1162 struct rt_addrinfo info;
1163 struct sockaddr *sa = NULL;
1164 int pass;
1165 struct mbuf *m = NULL;
1166 struct ifnet *ifp = ifa->ifa_ifp;
1167
1168 KASSERT(cmd == RTM_ADD || cmd == RTM_DELETE,
1169 ("unexpected cmd %u", cmd));
1170 #ifdef SCTP
1171 /*
1172 * notify the SCTP stack
1173 * this will only get called when an address is added/deleted
1174 * XXX pass the ifaddr struct instead if ifa->ifa_addr...
1175 */
1176 sctp_addr_change(ifa, cmd);
1177 #endif /* SCTP */
1178 if (route_cb.any_count == 0)
1179 return;
1180 for (pass = 1; pass < 3; pass++) {
1181 bzero((caddr_t)&info, sizeof(info));
1182 if ((cmd == RTM_ADD && pass == 1) ||
1183 (cmd == RTM_DELETE && pass == 2)) {
1184 struct ifa_msghdr *ifam;
1185 int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR;
1186
1187 info.rti_info[RTAX_IFA] = sa = ifa->ifa_addr;
1188 info.rti_info[RTAX_IFP] = ifp->if_addr->ifa_addr;
1189 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
1190 info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
1191 if ((m = rt_msg1(ncmd, &info)) == NULL)
1192 continue;
1193 ifam = mtod(m, struct ifa_msghdr *);
1194 ifam->ifam_index = ifp->if_index;
1195 ifam->ifam_metric = ifa->ifa_metric;
1196 ifam->ifam_flags = ifa->ifa_flags;
1197 ifam->ifam_addrs = info.rti_addrs;
1198 }
1199 if ((cmd == RTM_ADD && pass == 2) ||
1200 (cmd == RTM_DELETE && pass == 1)) {
1201 struct rt_msghdr *rtm;
1202
1203 if (rt == NULL)
1204 continue;
1205 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
1206 info.rti_info[RTAX_DST] = sa = rt_key(rt);
1207 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
1208 if ((m = rt_msg1(cmd, &info)) == NULL)
1209 continue;
1210 rtm = mtod(m, struct rt_msghdr *);
1211 rtm->rtm_index = ifp->if_index;
1212 rtm->rtm_flags |= rt->rt_flags;
1213 rtm->rtm_errno = error;
1214 rtm->rtm_addrs = info.rti_addrs;
1215 }
1216 if (fibnum != RTS_ALLFIBS) {
1217 KASSERT(fibnum >= 0 && fibnum < rt_numfibs, ("%s: "
1218 "fibnum out of range 0 <= %d < %d", __func__,
1219 fibnum, rt_numfibs));
1220 M_SETFIB(m, fibnum);
1221 m->m_flags |= RTS_FILTER_FIB;
1222 }
1223 rt_dispatch(m, sa);
1224 }
1225 }
1226
1227 void
1228 rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
1229 {
1230
1231 rt_newaddrmsg_fib(cmd, ifa, error, rt, RTS_ALLFIBS);
1232 }
1233
1234 /*
1235 * This is the analogue to the rt_newaddrmsg which performs the same
1236 * function but for multicast group memberhips. This is easier since
1237 * there is no route state to worry about.
1238 */
1239 void
1240 rt_newmaddrmsg(int cmd, struct ifmultiaddr *ifma)
1241 {
1242 struct rt_addrinfo info;
1243 struct mbuf *m = NULL;
1244 struct ifnet *ifp = ifma->ifma_ifp;
1245 struct ifma_msghdr *ifmam;
1246
1247 if (route_cb.any_count == 0)
1248 return;
1249
1250 bzero((caddr_t)&info, sizeof(info));
1251 info.rti_info[RTAX_IFA] = ifma->ifma_addr;
1252 info.rti_info[RTAX_IFP] = ifp ? ifp->if_addr->ifa_addr : NULL;
1253 /*
1254 * If a link-layer address is present, present it as a ``gateway''
1255 * (similarly to how ARP entries, e.g., are presented).
1256 */
1257 info.rti_info[RTAX_GATEWAY] = ifma->ifma_lladdr;
1258 m = rt_msg1(cmd, &info);
1259 if (m == NULL)
1260 return;
1261 ifmam = mtod(m, struct ifma_msghdr *);
1262 KASSERT(ifp != NULL, ("%s: link-layer multicast address w/o ifp\n",
1263 __func__));
1264 ifmam->ifmam_index = ifp->if_index;
1265 ifmam->ifmam_addrs = info.rti_addrs;
1266 rt_dispatch(m, ifma->ifma_addr);
1267 }
1268
1269 static struct mbuf *
1270 rt_makeifannouncemsg(struct ifnet *ifp, int type, int what,
1271 struct rt_addrinfo *info)
1272 {
1273 struct if_announcemsghdr *ifan;
1274 struct mbuf *m;
1275
1276 if (route_cb.any_count == 0)
1277 return NULL;
1278 bzero((caddr_t)info, sizeof(*info));
1279 m = rt_msg1(type, info);
1280 if (m != NULL) {
1281 ifan = mtod(m, struct if_announcemsghdr *);
1282 ifan->ifan_index = ifp->if_index;
1283 strlcpy(ifan->ifan_name, ifp->if_xname,
1284 sizeof(ifan->ifan_name));
1285 ifan->ifan_what = what;
1286 }
1287 return m;
1288 }
1289
1290 /*
1291 * This is called to generate routing socket messages indicating
1292 * IEEE80211 wireless events.
1293 * XXX we piggyback on the RTM_IFANNOUNCE msg format in a clumsy way.
1294 */
1295 void
1296 rt_ieee80211msg(struct ifnet *ifp, int what, void *data, size_t data_len)
1297 {
1298 struct mbuf *m;
1299 struct rt_addrinfo info;
1300
1301 m = rt_makeifannouncemsg(ifp, RTM_IEEE80211, what, &info);
1302 if (m != NULL) {
1303 /*
1304 * Append the ieee80211 data. Try to stick it in the
1305 * mbuf containing the ifannounce msg; otherwise allocate
1306 * a new mbuf and append.
1307 *
1308 * NB: we assume m is a single mbuf.
1309 */
1310 if (data_len > M_TRAILINGSPACE(m)) {
1311 struct mbuf *n = m_get(M_NOWAIT, MT_DATA);
1312 if (n == NULL) {
1313 m_freem(m);
1314 return;
1315 }
1316 bcopy(data, mtod(n, void *), data_len);
1317 n->m_len = data_len;
1318 m->m_next = n;
1319 } else if (data_len > 0) {
1320 bcopy(data, mtod(m, u_int8_t *) + m->m_len, data_len);
1321 m->m_len += data_len;
1322 }
1323 if (m->m_flags & M_PKTHDR)
1324 m->m_pkthdr.len += data_len;
1325 mtod(m, struct if_announcemsghdr *)->ifan_msglen += data_len;
1326 rt_dispatch(m, NULL);
1327 }
1328 }
1329
1330 /*
1331 * This is called to generate routing socket messages indicating
1332 * network interface arrival and departure.
1333 */
1334 void
1335 rt_ifannouncemsg(struct ifnet *ifp, int what)
1336 {
1337 struct mbuf *m;
1338 struct rt_addrinfo info;
1339
1340 m = rt_makeifannouncemsg(ifp, RTM_IFANNOUNCE, what, &info);
1341 if (m != NULL)
1342 rt_dispatch(m, NULL);
1343 }
1344
1345 static void
1346 rt_dispatch(struct mbuf *m, const struct sockaddr *sa)
1347 {
1348 struct m_tag *tag;
1349
1350 /*
1351 * Preserve the family from the sockaddr, if any, in an m_tag for
1352 * use when injecting the mbuf into the routing socket buffer from
1353 * the netisr.
1354 */
1355 if (sa != NULL) {
1356 tag = m_tag_get(PACKET_TAG_RTSOCKFAM, sizeof(unsigned short),
1357 M_NOWAIT);
1358 if (tag == NULL) {
1359 m_freem(m);
1360 return;
1361 }
1362 *(unsigned short *)(tag + 1) = sa->sa_family;
1363 m_tag_prepend(m, tag);
1364 }
1365 netisr_queue(NETISR_ROUTE, m); /* mbuf is free'd on failure. */
1366 }
1367
1368 /*
1369 * This is used in dumping the kernel table via sysctl().
1370 */
1371 static int
1372 sysctl_dumpentry(struct radix_node *rn, void *vw)
1373 {
1374 struct walkarg *w = vw;
1375 struct rtentry *rt = (struct rtentry *)rn;
1376 int error = 0, size;
1377 struct rt_addrinfo info;
1378
1379 if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
1380 return 0;
1381 if ((rt->rt_flags & RTF_HOST) == 0
1382 ? jailed(w->w_req->td->td_ucred)
1383 : prison_if(w->w_req->td->td_ucred, rt_key(rt)) != 0)
1384 return (0);
1385 bzero((caddr_t)&info, sizeof(info));
1386 info.rti_info[RTAX_DST] = rt_key(rt);
1387 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
1388 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
1389 info.rti_info[RTAX_GENMASK] = rt->rt_genmask;
1390 if (rt->rt_ifp) {
1391 info.rti_info[RTAX_IFP] = rt->rt_ifp->if_addr->ifa_addr;
1392 info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
1393 if (rt->rt_ifp->if_flags & IFF_POINTOPOINT)
1394 info.rti_info[RTAX_BRD] = rt->rt_ifa->ifa_dstaddr;
1395 }
1396 size = rt_msg2(RTM_GET, &info, NULL, w);
1397 if (w->w_req && w->w_tmem) {
1398 struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
1399
1400 rtm->rtm_flags = rt->rt_flags;
1401 rtm->rtm_use = rt->rt_rmx.rmx_pksent;
1402 rt_getmetrics(&rt->rt_rmx, &rtm->rtm_rmx);
1403 rtm->rtm_index = rt->rt_ifp->if_index;
1404 rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
1405 rtm->rtm_addrs = info.rti_addrs;
1406 error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size);
1407 return (error);
1408 }
1409 return (error);
1410 }
1411
1412 static int
1413 sysctl_iflist_ifml(struct ifnet *ifp, struct rt_addrinfo *info,
1414 struct walkarg *w, int len)
1415 {
1416 struct if_msghdrl *ifm;
1417
1418 #ifdef COMPAT_FREEBSD32
1419 if (w->w_req->flags & SCTL_MASK32) {
1420 struct if_msghdrl32 *ifm32;
1421
1422 ifm32 = (struct if_msghdrl32 *)w->w_tmem;
1423 ifm32->ifm_addrs = info->rti_addrs;
1424 ifm32->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
1425 ifm32->ifm_index = ifp->if_index;
1426 ifm32->_ifm_spare1 = 0;
1427 ifm32->ifm_len = sizeof(*ifm32);
1428 ifm32->ifm_data_off = offsetof(struct if_msghdrl32, ifm_data);
1429
1430 copy_ifdata32(&ifp->if_data, &ifm32->ifm_data);
1431
1432 return (SYSCTL_OUT(w->w_req, (caddr_t)ifm32, len));
1433 }
1434 #endif
1435 ifm = (struct if_msghdrl *)w->w_tmem;
1436 ifm->ifm_addrs = info->rti_addrs;
1437 ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
1438 ifm->ifm_index = ifp->if_index;
1439 ifm->_ifm_spare1 = 0;
1440 ifm->ifm_len = sizeof(*ifm);
1441 ifm->ifm_data_off = offsetof(struct if_msghdrl, ifm_data);
1442
1443 ifm->ifm_data = ifp->if_data;
1444
1445 return (SYSCTL_OUT(w->w_req, (caddr_t)ifm, len));
1446 }
1447
1448 static int
1449 sysctl_iflist_ifm(struct ifnet *ifp, struct rt_addrinfo *info,
1450 struct walkarg *w, int len)
1451 {
1452 struct if_msghdr *ifm;
1453
1454 #ifdef COMPAT_FREEBSD32
1455 if (w->w_req->flags & SCTL_MASK32) {
1456 struct if_msghdr32 *ifm32;
1457
1458 ifm32 = (struct if_msghdr32 *)w->w_tmem;
1459 ifm32->ifm_addrs = info->rti_addrs;
1460 ifm32->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
1461 ifm32->ifm_index = ifp->if_index;
1462
1463 copy_ifdata32(&ifp->if_data, &ifm32->ifm_data);
1464
1465 return (SYSCTL_OUT(w->w_req, (caddr_t)ifm32, len));
1466 }
1467 #endif
1468 ifm = (struct if_msghdr *)w->w_tmem;
1469 ifm->ifm_addrs = info->rti_addrs;
1470 ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
1471 ifm->ifm_index = ifp->if_index;
1472
1473 ifm->ifm_data = ifp->if_data;
1474
1475 return (SYSCTL_OUT(w->w_req, (caddr_t)ifm, len));
1476 }
1477
1478 static int
1479 sysctl_iflist_ifaml(struct ifaddr *ifa, struct rt_addrinfo *info,
1480 struct walkarg *w, int len)
1481 {
1482 struct ifa_msghdrl *ifam;
1483
1484 #ifdef COMPAT_FREEBSD32
1485 if (w->w_req->flags & SCTL_MASK32) {
1486 struct ifa_msghdrl32 *ifam32;
1487
1488 ifam32 = (struct ifa_msghdrl32 *)w->w_tmem;
1489 ifam32->ifam_addrs = info->rti_addrs;
1490 ifam32->ifam_flags = ifa->ifa_flags;
1491 ifam32->ifam_index = ifa->ifa_ifp->if_index;
1492 ifam32->_ifam_spare1 = 0;
1493 ifam32->ifam_len = sizeof(*ifam32);
1494 ifam32->ifam_data_off =
1495 offsetof(struct ifa_msghdrl32, ifam_data);
1496 ifam32->ifam_metric = ifa->ifa_metric;
1497
1498 copy_ifdata32(&ifa->ifa_ifp->if_data, &ifam32->ifam_data);
1499
1500 return (SYSCTL_OUT(w->w_req, (caddr_t)ifam32, len));
1501 }
1502 #endif
1503
1504 ifam = (struct ifa_msghdrl *)w->w_tmem;
1505 ifam->ifam_addrs = info->rti_addrs;
1506 ifam->ifam_flags = ifa->ifa_flags;
1507 ifam->ifam_index = ifa->ifa_ifp->if_index;
1508 ifam->_ifam_spare1 = 0;
1509 ifam->ifam_len = sizeof(*ifam);
1510 ifam->ifam_data_off = offsetof(struct ifa_msghdrl, ifam_data);
1511 ifam->ifam_metric = ifa->ifa_metric;
1512
1513 ifam->ifam_data = ifa->if_data;
1514
1515 return (SYSCTL_OUT(w->w_req, w->w_tmem, len));
1516 }
1517
1518 static int
1519 sysctl_iflist_ifam(struct ifaddr *ifa, struct rt_addrinfo *info,
1520 struct walkarg *w, int len)
1521 {
1522 struct ifa_msghdr *ifam;
1523
1524 ifam = (struct ifa_msghdr *)w->w_tmem;
1525 ifam->ifam_addrs = info->rti_addrs;
1526 ifam->ifam_flags = ifa->ifa_flags;
1527 ifam->ifam_index = ifa->ifa_ifp->if_index;
1528 ifam->ifam_metric = ifa->ifa_metric;
1529
1530 return (SYSCTL_OUT(w->w_req, w->w_tmem, len));
1531 }
1532
1533 static int
1534 sysctl_iflist(int af, struct walkarg *w)
1535 {
1536 struct ifnet *ifp;
1537 struct ifaddr *ifa;
1538 struct rt_addrinfo info;
1539 int len, error = 0;
1540
1541 bzero((caddr_t)&info, sizeof(info));
1542 IFNET_RLOCK();
1543 TAILQ_FOREACH(ifp, &ifnet, if_link) {
1544 if (w->w_arg && w->w_arg != ifp->if_index)
1545 continue;
1546 IF_ADDR_LOCK(ifp);
1547 ifa = ifp->if_addr;
1548 info.rti_info[RTAX_IFP] = ifa->ifa_addr;
1549 len = rt_msg2(RTM_IFINFO, &info, NULL, w);
1550 info.rti_info[RTAX_IFP] = NULL;
1551 if (w->w_req && w->w_tmem) {
1552 if (w->w_op == NET_RT_IFLISTL)
1553 error = sysctl_iflist_ifml(ifp, &info, w, len);
1554 else
1555 error = sysctl_iflist_ifm(ifp, &info, w, len);
1556 if (error)
1557 goto done;
1558 }
1559 while ((ifa = TAILQ_NEXT(ifa, ifa_link)) != NULL) {
1560 if (af && af != ifa->ifa_addr->sa_family)
1561 continue;
1562 if (prison_if(w->w_req->td->td_ucred,
1563 ifa->ifa_addr) != 0)
1564 continue;
1565 info.rti_info[RTAX_IFA] = ifa->ifa_addr;
1566 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
1567 info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
1568 len = rt_msg2(RTM_NEWADDR, &info, NULL, w);
1569 if (w->w_req && w->w_tmem) {
1570 if (w->w_op == NET_RT_IFLISTL)
1571 error = sysctl_iflist_ifaml(ifa, &info,
1572 w, len);
1573 else
1574 error = sysctl_iflist_ifam(ifa, &info,
1575 w, len);
1576 if (error)
1577 goto done;
1578 }
1579 }
1580 IF_ADDR_UNLOCK(ifp);
1581 info.rti_info[RTAX_IFA] = info.rti_info[RTAX_NETMASK] =
1582 info.rti_info[RTAX_BRD] = NULL;
1583 }
1584 done:
1585 if (ifp != NULL)
1586 IF_ADDR_UNLOCK(ifp);
1587 IFNET_RUNLOCK();
1588 return (error);
1589 }
1590
1591 static int
1592 sysctl_ifmalist(int af, struct walkarg *w)
1593 {
1594 struct ifnet *ifp;
1595 struct ifmultiaddr *ifma;
1596 struct rt_addrinfo info;
1597 int len, error = 0;
1598 struct ifaddr *ifa;
1599
1600 bzero((caddr_t)&info, sizeof(info));
1601 IFNET_RLOCK();
1602 TAILQ_FOREACH(ifp, &ifnet, if_link) {
1603 if (w->w_arg && w->w_arg != ifp->if_index)
1604 continue;
1605 ifa = ifp->if_addr;
1606 info.rti_info[RTAX_IFP] = ifa ? ifa->ifa_addr : NULL;
1607 IF_ADDR_LOCK(ifp);
1608 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1609 if (af && af != ifma->ifma_addr->sa_family)
1610 continue;
1611 if (prison_if(w->w_req->td->td_ucred,
1612 ifma->ifma_addr) != 0)
1613 continue;
1614 info.rti_info[RTAX_IFA] = ifma->ifma_addr;
1615 info.rti_info[RTAX_GATEWAY] =
1616 (ifma->ifma_addr->sa_family != AF_LINK) ?
1617 ifma->ifma_lladdr : NULL;
1618 len = rt_msg2(RTM_NEWMADDR, &info, NULL, w);
1619 if (w->w_req && w->w_tmem) {
1620 struct ifma_msghdr *ifmam;
1621
1622 ifmam = (struct ifma_msghdr *)w->w_tmem;
1623 ifmam->ifmam_index = ifma->ifma_ifp->if_index;
1624 ifmam->ifmam_flags = 0;
1625 ifmam->ifmam_addrs = info.rti_addrs;
1626 error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
1627 if (error) {
1628 IF_ADDR_UNLOCK(ifp);
1629 goto done;
1630 }
1631 }
1632 }
1633 IF_ADDR_UNLOCK(ifp);
1634 }
1635 done:
1636 IFNET_RUNLOCK();
1637 return (error);
1638 }
1639
1640 static int
1641 sysctl_rtsock(SYSCTL_HANDLER_ARGS)
1642 {
1643 int *name = (int *)arg1;
1644 u_int namelen = arg2;
1645 struct radix_node_head *rnh;
1646 int i, lim, error = EINVAL;
1647 u_char af;
1648 struct walkarg w;
1649
1650 name ++;
1651 namelen--;
1652 if (req->newptr)
1653 return (EPERM);
1654 if (namelen != 3)
1655 return ((namelen < 3) ? EISDIR : ENOTDIR);
1656 af = name[0];
1657 if (af > AF_MAX)
1658 return (EINVAL);
1659 bzero(&w, sizeof(w));
1660 w.w_op = name[1];
1661 w.w_arg = name[2];
1662 w.w_req = req;
1663
1664 error = sysctl_wire_old_buffer(req, 0);
1665 if (error)
1666 return (error);
1667 switch (w.w_op) {
1668
1669 case NET_RT_DUMP:
1670 case NET_RT_FLAGS:
1671 if (af == 0) { /* dump all tables */
1672 i = 1;
1673 lim = AF_MAX;
1674 } else /* dump only one table */
1675 i = lim = af;
1676 for (error = 0; error == 0 && i <= lim; i++)
1677 if ((rnh = rt_tables[req->td->td_proc->p_fibnum][i]) != NULL) {
1678 RADIX_NODE_HEAD_LOCK(rnh);
1679 error = rnh->rnh_walktree(rnh,
1680 sysctl_dumpentry, &w);
1681 RADIX_NODE_HEAD_UNLOCK(rnh);
1682 } else if (af != 0)
1683 error = EAFNOSUPPORT;
1684 break;
1685
1686 case NET_RT_IFLIST:
1687 case NET_RT_IFLISTL:
1688 error = sysctl_iflist(af, &w);
1689 break;
1690
1691 case NET_RT_IFMALIST:
1692 error = sysctl_ifmalist(af, &w);
1693 break;
1694 }
1695 if (w.w_tmem)
1696 free(w.w_tmem, M_RTABLE);
1697 return (error);
1698 }
1699
1700 SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock, "");
1701
1702 /*
1703 * Definitions of protocols supported in the ROUTE domain.
1704 */
1705
1706 static struct domain routedomain; /* or at least forward */
1707
1708 static struct protosw routesw[] = {
1709 {
1710 .pr_type = SOCK_RAW,
1711 .pr_domain = &routedomain,
1712 .pr_flags = PR_ATOMIC|PR_ADDR,
1713 .pr_output = route_output,
1714 .pr_ctlinput = raw_ctlinput,
1715 .pr_init = raw_init,
1716 .pr_usrreqs = &route_usrreqs
1717 }
1718 };
1719
1720 static struct domain routedomain = {
1721 .dom_family = PF_ROUTE,
1722 .dom_name = "route",
1723 .dom_protosw = routesw,
1724 .dom_protoswNPROTOSW = &routesw[sizeof(routesw)/sizeof(routesw[0])]
1725 };
1726
1727 DOMAIN_SET(route);
Cache object: b76d196b4a1dcce3242e69bcc5f0b48b
|