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
33 #include <sys/param.h>
34 #include <sys/domain.h>
35 #include <sys/kernel.h>
36 #include <sys/jail.h>
37 #include <sys/malloc.h>
38 #include <sys/mbuf.h>
39 #include <sys/proc.h>
40 #include <sys/protosw.h>
41 #include <sys/signalvar.h>
42 #include <sys/socket.h>
43 #include <sys/socketvar.h>
44 #include <sys/sysctl.h>
45 #include <sys/systm.h>
46
47 #include <net/if.h>
48 #include <net/netisr.h>
49 #include <net/raw_cb.h>
50 #include <net/route.h>
51
52 #include <netinet/in.h>
53
54 MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables");
55
56 /* NB: these are not modified */
57 static struct sockaddr route_dst = { 2, PF_ROUTE, };
58 static struct sockaddr route_src = { 2, PF_ROUTE, };
59 static struct sockaddr sa_zero = { sizeof(sa_zero), AF_INET, };
60
61 static struct {
62 int ip_count; /* attached w/ AF_INET */
63 int ip6_count; /* attached w/ AF_INET6 */
64 int ipx_count; /* attached w/ AF_IPX */
65 int any_count; /* total attached */
66 } route_cb;
67
68 struct mtx rtsock_mtx;
69 MTX_SYSINIT(rtsock, &rtsock_mtx, "rtsock route_cb lock", MTX_DEF);
70
71 #define RTSOCK_LOCK() mtx_lock(&rtsock_mtx)
72 #define RTSOCK_UNLOCK() mtx_unlock(&rtsock_mtx)
73 #define RTSOCK_LOCK_ASSERT() mtx_assert(&rtsock_mtx, MA_OWNED)
74
75 static struct ifqueue rtsintrq;
76
77 SYSCTL_NODE(_net, OID_AUTO, route, CTLFLAG_RD, 0, "");
78 SYSCTL_INT(_net_route, OID_AUTO, netisr_maxqlen, CTLFLAG_RW,
79 &rtsintrq.ifq_maxlen, 0, "maximum routing socket dispatch queue length");
80
81 struct walkarg {
82 int w_tmemsize;
83 int w_op, w_arg;
84 caddr_t w_tmem;
85 struct sysctl_req *w_req;
86 };
87
88 static void rts_input(struct mbuf *m);
89 static struct mbuf *rt_msg1(int type, struct rt_addrinfo *rtinfo);
90 static int rt_msg2(int type, struct rt_addrinfo *rtinfo,
91 caddr_t cp, struct walkarg *w);
92 static int rt_xaddrs(caddr_t cp, caddr_t cplim,
93 struct rt_addrinfo *rtinfo);
94 static int sysctl_dumpentry(struct radix_node *rn, void *vw);
95 static int sysctl_iflist(int af, struct walkarg *w);
96 static int sysctl_ifmalist(int af, struct walkarg *w);
97 static int route_output(struct mbuf *m, struct socket *so);
98 static void rt_setmetrics(u_long which, const struct rt_metrics *in,
99 struct rt_metrics_lite *out);
100 static void rt_getmetrics(const struct rt_metrics_lite *in,
101 struct rt_metrics *out);
102 static void rt_dispatch(struct mbuf *, const struct sockaddr *);
103
104 static void
105 rts_init(void)
106 {
107 int tmp;
108
109 rtsintrq.ifq_maxlen = 256;
110 if (TUNABLE_INT_FETCH("net.route.netisr_maxqlen", &tmp))
111 rtsintrq.ifq_maxlen = tmp;
112 mtx_init(&rtsintrq.ifq_mtx, "rts_inq", NULL, MTX_DEF);
113 netisr_register(NETISR_ROUTE, rts_input, &rtsintrq, NETISR_MPSAFE);
114 }
115 SYSINIT(rtsock, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, rts_init, 0)
116
117 static void
118 rts_input(struct mbuf *m)
119 {
120 struct sockproto route_proto;
121 unsigned short *family;
122 struct m_tag *tag;
123
124 route_proto.sp_family = PF_ROUTE;
125 tag = m_tag_find(m, PACKET_TAG_RTSOCKFAM, NULL);
126 if (tag != NULL) {
127 family = (unsigned short *)(tag + 1);
128 route_proto.sp_protocol = *family;
129 m_tag_delete(m, tag);
130 } else
131 route_proto.sp_protocol = 0;
132
133 raw_input(m, &route_proto, &route_src, &route_dst);
134 }
135
136 /*
137 * It really doesn't make any sense at all for this code to share much
138 * with raw_usrreq.c, since its functionality is so restricted. XXX
139 */
140 static int
141 rts_abort(struct socket *so)
142 {
143
144 return (raw_usrreqs.pru_abort(so));
145 }
146
147 /* pru_accept is EOPNOTSUPP */
148
149 static int
150 rts_attach(struct socket *so, int proto, struct thread *td)
151 {
152 struct rawcb *rp;
153 int s, error;
154
155 if (sotorawcb(so) != NULL)
156 return EISCONN; /* XXX panic? */
157 /* XXX */
158 MALLOC(rp, struct rawcb *, sizeof *rp, M_PCB, M_WAITOK | M_ZERO);
159 if (rp == NULL)
160 return ENOBUFS;
161
162 /*
163 * The splnet() is necessary to block protocols from sending
164 * error notifications (like RTM_REDIRECT or RTM_LOSING) while
165 * this PCB is extant but incompletely initialized.
166 * Probably we should try to do more of this work beforehand and
167 * eliminate the spl.
168 */
169 s = splnet();
170 so->so_pcb = (caddr_t)rp;
171 error = raw_attach(so, proto);
172 rp = sotorawcb(so);
173 if (error) {
174 splx(s);
175 so->so_pcb = NULL;
176 free(rp, M_PCB);
177 return error;
178 }
179 RTSOCK_LOCK();
180 switch(rp->rcb_proto.sp_protocol) {
181 case AF_INET:
182 route_cb.ip_count++;
183 break;
184 case AF_INET6:
185 route_cb.ip6_count++;
186 break;
187 case AF_IPX:
188 route_cb.ipx_count++;
189 break;
190 }
191 rp->rcb_faddr = &route_src;
192 route_cb.any_count++;
193 RTSOCK_UNLOCK();
194 soisconnected(so);
195 so->so_options |= SO_USELOOPBACK;
196 splx(s);
197 return 0;
198 }
199
200 static int
201 rts_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
202 {
203
204 return (raw_usrreqs.pru_bind(so, nam, td)); /* xxx just EINVAL */
205 }
206
207 static int
208 rts_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
209 {
210
211 return (raw_usrreqs.pru_connect(so, nam, td)); /* XXX just EINVAL */
212 }
213
214 /* pru_connect2 is EOPNOTSUPP */
215 /* pru_control is EOPNOTSUPP */
216
217 static int
218 rts_detach(struct socket *so)
219 {
220 struct rawcb *rp = sotorawcb(so);
221 int s, error;
222
223 s = splnet();
224 if (rp != NULL) {
225 RTSOCK_LOCK();
226 switch(rp->rcb_proto.sp_protocol) {
227 case AF_INET:
228 route_cb.ip_count--;
229 break;
230 case AF_INET6:
231 route_cb.ip6_count--;
232 break;
233 case AF_IPX:
234 route_cb.ipx_count--;
235 break;
236 }
237 route_cb.any_count--;
238 RTSOCK_UNLOCK();
239 }
240 error = raw_usrreqs.pru_detach(so);
241 splx(s);
242 return error;
243 }
244
245 static int
246 rts_disconnect(struct socket *so)
247 {
248
249 return (raw_usrreqs.pru_disconnect(so));
250 }
251
252 /* pru_listen is EOPNOTSUPP */
253
254 static int
255 rts_peeraddr(struct socket *so, struct sockaddr **nam)
256 {
257
258 return (raw_usrreqs.pru_peeraddr(so, nam));
259 }
260
261 /* pru_rcvd is EOPNOTSUPP */
262 /* pru_rcvoob is EOPNOTSUPP */
263
264 static int
265 rts_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
266 struct mbuf *control, struct thread *td)
267 {
268
269 return (raw_usrreqs.pru_send(so, flags, m, nam, control, td));
270 }
271
272 /* pru_sense is null */
273
274 static int
275 rts_shutdown(struct socket *so)
276 {
277
278 return (raw_usrreqs.pru_shutdown(so));
279 }
280
281 static int
282 rts_sockaddr(struct socket *so, struct sockaddr **nam)
283 {
284
285 return (raw_usrreqs.pru_sockaddr(so, nam));
286 }
287
288 static struct pr_usrreqs route_usrreqs = {
289 rts_abort, pru_accept_notsupp, rts_attach, rts_bind, rts_connect,
290 pru_connect2_notsupp, pru_control_notsupp, rts_detach, rts_disconnect,
291 pru_listen_notsupp, rts_peeraddr, pru_rcvd_notsupp, pru_rcvoob_notsupp,
292 rts_send, pru_sense_null, rts_shutdown, rts_sockaddr,
293 sosend, soreceive, sopoll, pru_sosetlabel_null
294 };
295
296 /*ARGSUSED*/
297 static int
298 route_output(struct mbuf *m, struct socket *so)
299 {
300 #define sa_equal(a1, a2) (bcmp((a1), (a2), (a1)->sa_len) == 0)
301 struct rt_msghdr *rtm = NULL;
302 struct rtentry *rt = NULL;
303 struct radix_node_head *rnh;
304 struct rt_addrinfo info;
305 int len, error = 0;
306 struct ifnet *ifp = NULL;
307 struct ifaddr *ifa = NULL;
308 struct sockaddr_in jail;
309
310 #define senderr(e) { error = e; goto flush;}
311 if (m == NULL || ((m->m_len < sizeof(long)) &&
312 (m = m_pullup(m, sizeof(long))) == NULL))
313 return (ENOBUFS);
314 if ((m->m_flags & M_PKTHDR) == 0)
315 panic("route_output");
316 len = m->m_pkthdr.len;
317 if (len < sizeof(*rtm) ||
318 len != mtod(m, struct rt_msghdr *)->rtm_msglen) {
319 info.rti_info[RTAX_DST] = NULL;
320 senderr(EINVAL);
321 }
322 R_Malloc(rtm, struct rt_msghdr *, len);
323 if (rtm == NULL) {
324 info.rti_info[RTAX_DST] = NULL;
325 senderr(ENOBUFS);
326 }
327 m_copydata(m, 0, len, (caddr_t)rtm);
328 if (rtm->rtm_version != RTM_VERSION) {
329 info.rti_info[RTAX_DST] = NULL;
330 senderr(EPROTONOSUPPORT);
331 }
332 rtm->rtm_pid = curproc->p_pid;
333 bzero(&info, sizeof(info));
334 info.rti_addrs = rtm->rtm_addrs;
335 if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info)) {
336 info.rti_info[RTAX_DST] = NULL;
337 senderr(EINVAL);
338 }
339 info.rti_flags = rtm->rtm_flags;
340 if (info.rti_info[RTAX_DST] == NULL ||
341 info.rti_info[RTAX_DST]->sa_family >= AF_MAX ||
342 (info.rti_info[RTAX_GATEWAY] != NULL &&
343 info.rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX))
344 senderr(EINVAL);
345 if (info.rti_info[RTAX_GENMASK]) {
346 struct radix_node *t;
347 t = rn_addmask((caddr_t) info.rti_info[RTAX_GENMASK], 0, 1);
348 if (t != NULL &&
349 bcmp((char *)(void *)info.rti_info[RTAX_GENMASK] + 1,
350 (char *)(void *)t->rn_key + 1,
351 ((struct sockaddr *)t->rn_key)->sa_len - 1) == 0)
352 info.rti_info[RTAX_GENMASK] =
353 (struct sockaddr *)t->rn_key;
354 else
355 senderr(ENOBUFS);
356 }
357
358 /*
359 * Verify that the caller has the appropriate privilege; RTM_GET
360 * is the only operation the non-superuser is allowed.
361 */
362 if (rtm->rtm_type != RTM_GET && (error = suser(curthread)) != 0)
363 senderr(error);
364
365 switch (rtm->rtm_type) {
366 struct rtentry *saved_nrt;
367
368 case RTM_ADD:
369 if (info.rti_info[RTAX_GATEWAY] == NULL)
370 senderr(EINVAL);
371 saved_nrt = NULL;
372 error = rtrequest1(RTM_ADD, &info, &saved_nrt);
373 if (error == 0 && saved_nrt) {
374 RT_LOCK(saved_nrt);
375 rt_setmetrics(rtm->rtm_inits,
376 &rtm->rtm_rmx, &saved_nrt->rt_rmx);
377 RT_REMREF(saved_nrt);
378 saved_nrt->rt_genmask = info.rti_info[RTAX_GENMASK];
379 RT_UNLOCK(saved_nrt);
380 }
381 break;
382
383 case RTM_DELETE:
384 saved_nrt = NULL;
385 error = rtrequest1(RTM_DELETE, &info, &saved_nrt);
386 if (error == 0) {
387 RT_LOCK(saved_nrt);
388 rt = saved_nrt;
389 goto report;
390 }
391 break;
392
393 case RTM_GET:
394 case RTM_CHANGE:
395 case RTM_LOCK:
396 rnh = rt_tables[info.rti_info[RTAX_DST]->sa_family];
397 if (rnh == NULL)
398 senderr(EAFNOSUPPORT);
399 RADIX_NODE_HEAD_LOCK(rnh);
400 rt = (struct rtentry *) rnh->rnh_lookup(info.rti_info[RTAX_DST],
401 info.rti_info[RTAX_NETMASK], rnh);
402 if (rt == NULL) { /* XXX looks bogus */
403 RADIX_NODE_HEAD_UNLOCK(rnh);
404 senderr(ESRCH);
405 }
406 RT_LOCK(rt);
407 RT_ADDREF(rt);
408 RADIX_NODE_HEAD_UNLOCK(rnh);
409
410 /*
411 * Fix for PR: 82974
412 *
413 * RTM_CHANGE/LOCK need a perfect match, rn_lookup()
414 * returns a perfect match in case a netmask is
415 * specified. For host routes only a longest prefix
416 * match is returned so it is necessary to compare the
417 * existence of the netmask. If both have a netmask
418 * rnh_lookup() did a perfect match and if none of them
419 * have a netmask both are host routes which is also a
420 * perfect match.
421 */
422
423 if (rtm->rtm_type != RTM_GET &&
424 (!rt_mask(rt) != !info.rti_info[RTAX_NETMASK])) {
425 RT_UNLOCK(rt);
426 senderr(ESRCH);
427 }
428
429 switch(rtm->rtm_type) {
430
431 case RTM_GET:
432 report:
433 RT_LOCK_ASSERT(rt);
434 info.rti_info[RTAX_DST] = rt_key(rt);
435 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
436 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
437 info.rti_info[RTAX_GENMASK] = rt->rt_genmask;
438 if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
439 ifp = rt->rt_ifp;
440 if (ifp) {
441 info.rti_info[RTAX_IFP] =
442 ifaddr_byindex(ifp->if_index)->ifa_addr;
443 if (jailed(so->so_cred)) {
444 bzero(&jail, sizeof(jail));
445 jail.sin_family = PF_INET;
446 jail.sin_len = sizeof(jail);
447 jail.sin_addr.s_addr =
448 htonl(prison_getip(so->so_cred));
449 info.rti_info[RTAX_IFA] =
450 (struct sockaddr *)&jail;
451 } else
452 info.rti_info[RTAX_IFA] =
453 rt->rt_ifa->ifa_addr;
454 if (ifp->if_flags & IFF_POINTOPOINT)
455 info.rti_info[RTAX_BRD] =
456 rt->rt_ifa->ifa_dstaddr;
457 rtm->rtm_index = ifp->if_index;
458 } else {
459 info.rti_info[RTAX_IFP] = NULL;
460 info.rti_info[RTAX_IFA] = NULL;
461 }
462 }
463 len = rt_msg2(rtm->rtm_type, &info, NULL, NULL);
464 if (len > rtm->rtm_msglen) {
465 struct rt_msghdr *new_rtm;
466 R_Malloc(new_rtm, struct rt_msghdr *, len);
467 if (new_rtm == NULL) {
468 RT_UNLOCK(rt);
469 senderr(ENOBUFS);
470 }
471 bcopy(rtm, new_rtm, rtm->rtm_msglen);
472 Free(rtm); rtm = new_rtm;
473 }
474 (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm, NULL);
475 rtm->rtm_flags = rt->rt_flags;
476 rt_getmetrics(&rt->rt_rmx, &rtm->rtm_rmx);
477 rtm->rtm_addrs = info.rti_addrs;
478 break;
479
480 case RTM_CHANGE:
481 /*
482 * New gateway could require new ifaddr, ifp;
483 * flags may also be different; ifp may be specified
484 * by ll sockaddr when protocol address is ambiguous
485 */
486 if (((rt->rt_flags & RTF_GATEWAY) &&
487 info.rti_info[RTAX_GATEWAY] != NULL) ||
488 info.rti_info[RTAX_IFP] != NULL ||
489 (info.rti_info[RTAX_IFA] != NULL &&
490 !sa_equal(info.rti_info[RTAX_IFA],
491 rt->rt_ifa->ifa_addr))) {
492 RT_UNLOCK(rt);
493 if ((error = rt_getifa(&info)) != 0)
494 senderr(error);
495 RT_LOCK(rt);
496 }
497 if (info.rti_info[RTAX_GATEWAY] != NULL &&
498 (error = rt_setgate(rt, rt_key(rt),
499 info.rti_info[RTAX_GATEWAY])) != 0) {
500 RT_UNLOCK(rt);
501 senderr(error);
502 }
503 if ((ifa = info.rti_ifa) != NULL) {
504 struct ifaddr *oifa = rt->rt_ifa;
505 if (oifa != ifa) {
506 if (oifa) {
507 if (oifa->ifa_rtrequest)
508 oifa->ifa_rtrequest(
509 RTM_DELETE, rt,
510 &info);
511 IFAFREE(oifa);
512 }
513 IFAREF(ifa);
514 rt->rt_ifa = ifa;
515 rt->rt_ifp = info.rti_ifp;
516 }
517 }
518 rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
519 &rt->rt_rmx);
520 if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
521 rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, &info);
522 if (info.rti_info[RTAX_GENMASK])
523 rt->rt_genmask = info.rti_info[RTAX_GENMASK];
524 /* FALLTHROUGH */
525 case RTM_LOCK:
526 /* We don't support locks anymore */
527 break;
528 }
529 RT_UNLOCK(rt);
530 break;
531
532 default:
533 senderr(EOPNOTSUPP);
534 }
535
536 flush:
537 if (rtm) {
538 if (error)
539 rtm->rtm_errno = error;
540 else
541 rtm->rtm_flags |= RTF_DONE;
542 }
543 if (rt) /* XXX can this be true? */
544 RTFREE(rt);
545 {
546 struct rawcb *rp = NULL;
547 /*
548 * Check to see if we don't want our own messages.
549 */
550 if ((so->so_options & SO_USELOOPBACK) == 0) {
551 if (route_cb.any_count <= 1) {
552 if (rtm)
553 Free(rtm);
554 m_freem(m);
555 return (error);
556 }
557 /* There is another listener, so construct message */
558 rp = sotorawcb(so);
559 }
560 if (rtm) {
561 m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
562 if (m->m_pkthdr.len < rtm->rtm_msglen) {
563 m_freem(m);
564 m = NULL;
565 } else if (m->m_pkthdr.len > rtm->rtm_msglen)
566 m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len);
567 Free(rtm);
568 }
569 if (m) {
570 if (rp) {
571 /*
572 * XXX insure we don't get a copy by
573 * invalidating our protocol
574 */
575 unsigned short family = rp->rcb_proto.sp_family;
576 rp->rcb_proto.sp_family = 0;
577 rt_dispatch(m, info.rti_info[RTAX_DST]);
578 rp->rcb_proto.sp_family = family;
579 } else
580 rt_dispatch(m, info.rti_info[RTAX_DST]);
581 }
582 }
583 return (error);
584 #undef sa_equal
585 }
586
587 static void
588 rt_setmetrics(u_long which, const struct rt_metrics *in,
589 struct rt_metrics_lite *out)
590 {
591 #define metric(f, e) if (which & (f)) out->e = in->e;
592 /*
593 * Only these are stored in the routing entry since introduction
594 * of tcp hostcache. The rest is ignored.
595 */
596 metric(RTV_MTU, rmx_mtu);
597 metric(RTV_EXPIRE, rmx_expire);
598 #undef metric
599 }
600
601 static void
602 rt_getmetrics(const struct rt_metrics_lite *in, struct rt_metrics *out)
603 {
604 #define metric(e) out->e = in->e;
605 bzero(out, sizeof(*out));
606 metric(rmx_mtu);
607 metric(rmx_expire);
608 #undef metric
609 }
610
611 /*
612 * Extract the addresses of the passed sockaddrs.
613 * Do a little sanity checking so as to avoid bad memory references.
614 * This data is derived straight from userland.
615 */
616 static int
617 rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo)
618 {
619 struct sockaddr *sa;
620 int i;
621
622 for (i = 0; i < RTAX_MAX && cp < cplim; i++) {
623 if ((rtinfo->rti_addrs & (1 << i)) == 0)
624 continue;
625 sa = (struct sockaddr *)cp;
626 /*
627 * It won't fit.
628 */
629 if (cp + sa->sa_len > cplim)
630 return (EINVAL);
631 /*
632 * there are no more.. quit now
633 * If there are more bits, they are in error.
634 * I've seen this. route(1) can evidently generate these.
635 * This causes kernel to core dump.
636 * for compatibility, If we see this, point to a safe address.
637 */
638 if (sa->sa_len == 0) {
639 rtinfo->rti_info[i] = &sa_zero;
640 return (0); /* should be EINVAL but for compat */
641 }
642 /* accept it */
643 rtinfo->rti_info[i] = sa;
644 cp += SA_SIZE(sa);
645 }
646 return (0);
647 }
648
649 static struct mbuf *
650 rt_msg1(int type, struct rt_addrinfo *rtinfo)
651 {
652 struct rt_msghdr *rtm;
653 struct mbuf *m;
654 int i;
655 struct sockaddr *sa;
656 int len, dlen;
657
658 switch (type) {
659
660 case RTM_DELADDR:
661 case RTM_NEWADDR:
662 len = sizeof(struct ifa_msghdr);
663 break;
664
665 case RTM_DELMADDR:
666 case RTM_NEWMADDR:
667 len = sizeof(struct ifma_msghdr);
668 break;
669
670 case RTM_IFINFO:
671 len = sizeof(struct if_msghdr);
672 break;
673
674 case RTM_IFANNOUNCE:
675 len = sizeof(struct if_announcemsghdr);
676 break;
677
678 default:
679 len = sizeof(struct rt_msghdr);
680 }
681 if (len > MCLBYTES)
682 panic("rt_msg1");
683 m = m_gethdr(M_DONTWAIT, MT_DATA);
684 if (m && len > MHLEN) {
685 MCLGET(m, M_DONTWAIT);
686 if ((m->m_flags & M_EXT) == 0) {
687 m_free(m);
688 m = NULL;
689 }
690 }
691 if (m == NULL)
692 return (m);
693 m->m_pkthdr.len = m->m_len = len;
694 m->m_pkthdr.rcvif = NULL;
695 rtm = mtod(m, struct rt_msghdr *);
696 bzero((caddr_t)rtm, len);
697 for (i = 0; i < RTAX_MAX; i++) {
698 if ((sa = rtinfo->rti_info[i]) == NULL)
699 continue;
700 rtinfo->rti_addrs |= (1 << i);
701 dlen = SA_SIZE(sa);
702 m_copyback(m, len, dlen, (caddr_t)sa);
703 len += dlen;
704 }
705 if (m->m_pkthdr.len != len) {
706 m_freem(m);
707 return (NULL);
708 }
709 rtm->rtm_msglen = len;
710 rtm->rtm_version = RTM_VERSION;
711 rtm->rtm_type = type;
712 return (m);
713 }
714
715 static int
716 rt_msg2(int type, struct rt_addrinfo *rtinfo, caddr_t cp, struct walkarg *w)
717 {
718 int i;
719 int len, dlen, second_time = 0;
720 caddr_t cp0;
721
722 rtinfo->rti_addrs = 0;
723 again:
724 switch (type) {
725
726 case RTM_DELADDR:
727 case RTM_NEWADDR:
728 len = sizeof(struct ifa_msghdr);
729 break;
730
731 case RTM_IFINFO:
732 len = sizeof(struct if_msghdr);
733 break;
734
735 case RTM_NEWMADDR:
736 len = sizeof(struct ifma_msghdr);
737 break;
738
739 default:
740 len = sizeof(struct rt_msghdr);
741 }
742 cp0 = cp;
743 if (cp0)
744 cp += len;
745 for (i = 0; i < RTAX_MAX; i++) {
746 struct sockaddr *sa;
747
748 if ((sa = rtinfo->rti_info[i]) == NULL)
749 continue;
750 rtinfo->rti_addrs |= (1 << i);
751 dlen = SA_SIZE(sa);
752 if (cp) {
753 bcopy((caddr_t)sa, cp, (unsigned)dlen);
754 cp += dlen;
755 }
756 len += dlen;
757 }
758 len = ALIGN(len);
759 if (cp == NULL && w != NULL && !second_time) {
760 struct walkarg *rw = w;
761
762 if (rw->w_req) {
763 if (rw->w_tmemsize < len) {
764 if (rw->w_tmem)
765 free(rw->w_tmem, M_RTABLE);
766 rw->w_tmem = (caddr_t)
767 malloc(len, M_RTABLE, M_NOWAIT);
768 if (rw->w_tmem)
769 rw->w_tmemsize = len;
770 }
771 if (rw->w_tmem) {
772 cp = rw->w_tmem;
773 second_time = 1;
774 goto again;
775 }
776 }
777 }
778 if (cp) {
779 struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
780
781 rtm->rtm_version = RTM_VERSION;
782 rtm->rtm_type = type;
783 rtm->rtm_msglen = len;
784 }
785 return (len);
786 }
787
788 /*
789 * This routine is called to generate a message from the routing
790 * socket indicating that a redirect has occured, a routing lookup
791 * has failed, or that a protocol has detected timeouts to a particular
792 * destination.
793 */
794 void
795 rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error)
796 {
797 struct rt_msghdr *rtm;
798 struct mbuf *m;
799 struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
800
801 if (route_cb.any_count == 0)
802 return;
803 m = rt_msg1(type, rtinfo);
804 if (m == NULL)
805 return;
806 rtm = mtod(m, struct rt_msghdr *);
807 rtm->rtm_flags = RTF_DONE | flags;
808 rtm->rtm_errno = error;
809 rtm->rtm_addrs = rtinfo->rti_addrs;
810 rt_dispatch(m, sa);
811 }
812
813 /*
814 * This routine is called to generate a message from the routing
815 * socket indicating that the status of a network interface has changed.
816 */
817 void
818 rt_ifmsg(struct ifnet *ifp)
819 {
820 struct if_msghdr *ifm;
821 struct mbuf *m;
822 struct rt_addrinfo info;
823
824 if (route_cb.any_count == 0)
825 return;
826 bzero((caddr_t)&info, sizeof(info));
827 m = rt_msg1(RTM_IFINFO, &info);
828 if (m == NULL)
829 return;
830 ifm = mtod(m, struct if_msghdr *);
831 ifm->ifm_index = ifp->if_index;
832 ifm->ifm_flags = ifp->if_flags;
833 ifm->ifm_data = ifp->if_data;
834 ifm->ifm_addrs = 0;
835 rt_dispatch(m, NULL);
836 }
837
838 /*
839 * This is called to generate messages from the routing socket
840 * indicating a network interface has had addresses associated with it.
841 * if we ever reverse the logic and replace messages TO the routing
842 * socket indicate a request to configure interfaces, then it will
843 * be unnecessary as the routing socket will automatically generate
844 * copies of it.
845 */
846 void
847 rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
848 {
849 struct rt_addrinfo info;
850 struct sockaddr *sa = NULL;
851 int pass;
852 struct mbuf *m = NULL;
853 struct ifnet *ifp = ifa->ifa_ifp;
854
855 if (route_cb.any_count == 0)
856 return;
857 for (pass = 1; pass < 3; pass++) {
858 bzero((caddr_t)&info, sizeof(info));
859 if ((cmd == RTM_ADD && pass == 1) ||
860 (cmd == RTM_DELETE && pass == 2)) {
861 struct ifa_msghdr *ifam;
862 int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR;
863
864 info.rti_info[RTAX_IFA] = sa = ifa->ifa_addr;
865 info.rti_info[RTAX_IFP] =
866 ifaddr_byindex(ifp->if_index)->ifa_addr;
867 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
868 info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
869 if ((m = rt_msg1(ncmd, &info)) == NULL)
870 continue;
871 ifam = mtod(m, struct ifa_msghdr *);
872 ifam->ifam_index = ifp->if_index;
873 ifam->ifam_metric = ifa->ifa_metric;
874 ifam->ifam_flags = ifa->ifa_flags;
875 ifam->ifam_addrs = info.rti_addrs;
876 }
877 if ((cmd == RTM_ADD && pass == 2) ||
878 (cmd == RTM_DELETE && pass == 1)) {
879 struct rt_msghdr *rtm;
880
881 if (rt == NULL)
882 continue;
883 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
884 info.rti_info[RTAX_DST] = sa = rt_key(rt);
885 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
886 if ((m = rt_msg1(cmd, &info)) == NULL)
887 continue;
888 rtm = mtod(m, struct rt_msghdr *);
889 rtm->rtm_index = ifp->if_index;
890 rtm->rtm_flags |= rt->rt_flags;
891 rtm->rtm_errno = error;
892 rtm->rtm_addrs = info.rti_addrs;
893 }
894 rt_dispatch(m, sa);
895 }
896 }
897
898 /*
899 * This is the analogue to the rt_newaddrmsg which performs the same
900 * function but for multicast group memberhips. This is easier since
901 * there is no route state to worry about.
902 */
903 void
904 rt_newmaddrmsg(int cmd, struct ifmultiaddr *ifma)
905 {
906 struct rt_addrinfo info;
907 struct mbuf *m = NULL;
908 struct ifnet *ifp = ifma->ifma_ifp;
909 struct ifma_msghdr *ifmam;
910
911 if (route_cb.any_count == 0)
912 return;
913
914 bzero((caddr_t)&info, sizeof(info));
915 info.rti_info[RTAX_IFA] = ifma->ifma_addr;
916 info.rti_info[RTAX_IFP] =
917 ifp ? ifaddr_byindex(ifp->if_index)->ifa_addr : NULL;
918 /*
919 * If a link-layer address is present, present it as a ``gateway''
920 * (similarly to how ARP entries, e.g., are presented).
921 */
922 info.rti_info[RTAX_GATEWAY] = ifma->ifma_lladdr;
923 m = rt_msg1(cmd, &info);
924 if (m == NULL)
925 return;
926 ifmam = mtod(m, struct ifma_msghdr *);
927 ifmam->ifmam_index = ifp->if_index;
928 ifmam->ifmam_addrs = info.rti_addrs;
929 rt_dispatch(m, ifma->ifma_addr);
930 }
931
932 /*
933 * This is called to generate routing socket messages indicating
934 * network interface arrival and departure.
935 */
936 void
937 rt_ifannouncemsg(struct ifnet *ifp, int what)
938 {
939 struct if_announcemsghdr *ifan;
940 struct mbuf *m;
941 struct rt_addrinfo info;
942
943 if (route_cb.any_count == 0)
944 return;
945 bzero((caddr_t)&info, sizeof(info));
946 m = rt_msg1(RTM_IFANNOUNCE, &info);
947 if (m == NULL)
948 return;
949 ifan = mtod(m, struct if_announcemsghdr *);
950 ifan->ifan_index = ifp->if_index;
951 strlcpy(ifan->ifan_name, ifp->if_xname, sizeof(ifan->ifan_name));
952 ifan->ifan_what = what;
953 rt_dispatch(m, NULL);
954 }
955
956 static void
957 rt_dispatch(struct mbuf *m, const struct sockaddr *sa)
958 {
959 unsigned short *family;
960 struct m_tag *tag;
961
962 /*
963 * Preserve the family from the sockaddr, if any, in an m_tag for
964 * use when injecting the mbuf into the routing socket buffer from
965 * the netisr.
966 */
967 if (sa != NULL) {
968 tag = m_tag_get(PACKET_TAG_RTSOCKFAM, sizeof(unsigned short),
969 M_NOWAIT);
970 if (tag == NULL) {
971 m_freem(m);
972 return;
973 }
974 family = (unsigned short *)(tag + 1);
975 *family = sa ? sa->sa_family : 0;
976 m_tag_prepend(m, tag);
977 }
978 netisr_queue(NETISR_ROUTE, m); /* mbuf is free'd on failure. */
979 }
980
981 /*
982 * This is used in dumping the kernel table via sysctl().
983 */
984 static int
985 sysctl_dumpentry(struct radix_node *rn, void *vw)
986 {
987 struct walkarg *w = vw;
988 struct rtentry *rt = (struct rtentry *)rn;
989 int error = 0, size;
990 struct rt_addrinfo info;
991
992 if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
993 return 0;
994 bzero((caddr_t)&info, sizeof(info));
995 info.rti_info[RTAX_DST] = rt_key(rt);
996 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
997 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
998 info.rti_info[RTAX_GENMASK] = rt->rt_genmask;
999 if (rt->rt_ifp) {
1000 info.rti_info[RTAX_IFP] =
1001 ifaddr_byindex(rt->rt_ifp->if_index)->ifa_addr;
1002 info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
1003 if (rt->rt_ifp->if_flags & IFF_POINTOPOINT)
1004 info.rti_info[RTAX_BRD] = rt->rt_ifa->ifa_dstaddr;
1005 }
1006 size = rt_msg2(RTM_GET, &info, NULL, w);
1007 if (w->w_req && w->w_tmem) {
1008 struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
1009
1010 rtm->rtm_flags = rt->rt_flags;
1011 rtm->rtm_use = rt->rt_rmx.rmx_pksent;
1012 rt_getmetrics(&rt->rt_rmx, &rtm->rtm_rmx);
1013 rtm->rtm_index = rt->rt_ifp->if_index;
1014 rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
1015 rtm->rtm_addrs = info.rti_addrs;
1016 error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size);
1017 return (error);
1018 }
1019 return (error);
1020 }
1021
1022 static int
1023 sysctl_iflist(int af, struct walkarg *w)
1024 {
1025 struct ifnet *ifp;
1026 struct ifaddr *ifa;
1027 struct rt_addrinfo info;
1028 int len, error = 0;
1029
1030 bzero((caddr_t)&info, sizeof(info));
1031 IFNET_RLOCK();
1032 TAILQ_FOREACH(ifp, &ifnet, if_link) {
1033 if (w->w_arg && w->w_arg != ifp->if_index)
1034 continue;
1035 ifa = ifaddr_byindex(ifp->if_index);
1036 info.rti_info[RTAX_IFP] = ifa->ifa_addr;
1037 len = rt_msg2(RTM_IFINFO, &info, NULL, w);
1038 info.rti_info[RTAX_IFP] = NULL;
1039 if (w->w_req && w->w_tmem) {
1040 struct if_msghdr *ifm;
1041
1042 ifm = (struct if_msghdr *)w->w_tmem;
1043 ifm->ifm_index = ifp->if_index;
1044 ifm->ifm_flags = ifp->if_flags;
1045 ifm->ifm_data = ifp->if_data;
1046 ifm->ifm_addrs = info.rti_addrs;
1047 error = SYSCTL_OUT(w->w_req,(caddr_t)ifm, len);
1048 if (error)
1049 goto done;
1050 }
1051 while ((ifa = TAILQ_NEXT(ifa, ifa_link)) != NULL) {
1052 if (af && af != ifa->ifa_addr->sa_family)
1053 continue;
1054 if (jailed(curthread->td_ucred) &&
1055 prison_if(curthread->td_ucred, ifa->ifa_addr))
1056 continue;
1057 info.rti_info[RTAX_IFA] = ifa->ifa_addr;
1058 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
1059 info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
1060 len = rt_msg2(RTM_NEWADDR, &info, NULL, w);
1061 if (w->w_req && w->w_tmem) {
1062 struct ifa_msghdr *ifam;
1063
1064 ifam = (struct ifa_msghdr *)w->w_tmem;
1065 ifam->ifam_index = ifa->ifa_ifp->if_index;
1066 ifam->ifam_flags = ifa->ifa_flags;
1067 ifam->ifam_metric = ifa->ifa_metric;
1068 ifam->ifam_addrs = info.rti_addrs;
1069 error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
1070 if (error)
1071 goto done;
1072 }
1073 }
1074 info.rti_info[RTAX_IFA] = info.rti_info[RTAX_NETMASK] =
1075 info.rti_info[RTAX_BRD] = NULL;
1076 }
1077 done:
1078 IFNET_RUNLOCK();
1079 return (error);
1080 }
1081
1082 int
1083 sysctl_ifmalist(int af, struct walkarg *w)
1084 {
1085 struct ifnet *ifp;
1086 struct ifmultiaddr *ifma;
1087 struct rt_addrinfo info;
1088 int len, error = 0;
1089 struct ifaddr *ifa;
1090
1091 bzero((caddr_t)&info, sizeof(info));
1092 IFNET_RLOCK();
1093 TAILQ_FOREACH(ifp, &ifnet, if_link) {
1094 if (w->w_arg && w->w_arg != ifp->if_index)
1095 continue;
1096 ifa = ifaddr_byindex(ifp->if_index);
1097 info.rti_info[RTAX_IFP] = ifa ? ifa->ifa_addr : NULL;
1098 IF_ADDR_LOCK(ifp);
1099 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1100 if (af && af != ifma->ifma_addr->sa_family)
1101 continue;
1102 if (jailed(curproc->p_ucred) &&
1103 prison_if(curproc->p_ucred, ifma->ifma_addr))
1104 continue;
1105 info.rti_info[RTAX_IFA] = ifma->ifma_addr;
1106 info.rti_info[RTAX_GATEWAY] =
1107 (ifma->ifma_addr->sa_family != AF_LINK) ?
1108 ifma->ifma_lladdr : NULL;
1109 len = rt_msg2(RTM_NEWMADDR, &info, NULL, w);
1110 if (w->w_req && w->w_tmem) {
1111 struct ifma_msghdr *ifmam;
1112
1113 ifmam = (struct ifma_msghdr *)w->w_tmem;
1114 ifmam->ifmam_index = ifma->ifma_ifp->if_index;
1115 ifmam->ifmam_flags = 0;
1116 ifmam->ifmam_addrs = info.rti_addrs;
1117 error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
1118 if (error) {
1119 IF_ADDR_UNLOCK(ifp);
1120 goto done;
1121 }
1122 }
1123 }
1124 IF_ADDR_UNLOCK(ifp);
1125 }
1126 done:
1127 IFNET_RUNLOCK();
1128 return (error);
1129 }
1130
1131 static int
1132 sysctl_rtsock(SYSCTL_HANDLER_ARGS)
1133 {
1134 int *name = (int *)arg1;
1135 u_int namelen = arg2;
1136 struct radix_node_head *rnh;
1137 int i, lim, error = EINVAL;
1138 u_char af;
1139 struct walkarg w;
1140
1141 name ++;
1142 namelen--;
1143 if (req->newptr)
1144 return (EPERM);
1145 if (namelen != 3)
1146 return ((namelen < 3) ? EISDIR : ENOTDIR);
1147 af = name[0];
1148 if (af > AF_MAX)
1149 return (EINVAL);
1150 bzero(&w, sizeof(w));
1151 w.w_op = name[1];
1152 w.w_arg = name[2];
1153 w.w_req = req;
1154
1155 error = sysctl_wire_old_buffer(req, 0);
1156 if (error)
1157 return (error);
1158 switch (w.w_op) {
1159
1160 case NET_RT_DUMP:
1161 case NET_RT_FLAGS:
1162 if (af == 0) { /* dump all tables */
1163 i = 1;
1164 lim = AF_MAX;
1165 } else /* dump only one table */
1166 i = lim = af;
1167 for (error = 0; error == 0 && i <= lim; i++)
1168 if ((rnh = rt_tables[i]) != NULL) {
1169 RADIX_NODE_HEAD_LOCK(rnh);
1170 error = rnh->rnh_walktree(rnh,
1171 sysctl_dumpentry, &w);
1172 RADIX_NODE_HEAD_UNLOCK(rnh);
1173 } else if (af != 0)
1174 error = EAFNOSUPPORT;
1175 break;
1176
1177 case NET_RT_IFLIST:
1178 error = sysctl_iflist(af, &w);
1179 break;
1180
1181 case NET_RT_IFMALIST:
1182 error = sysctl_ifmalist(af, &w);
1183 break;
1184 }
1185 if (w.w_tmem)
1186 free(w.w_tmem, M_RTABLE);
1187 return (error);
1188 }
1189
1190 SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock, "");
1191
1192 /*
1193 * Definitions of protocols supported in the ROUTE domain.
1194 */
1195
1196 extern struct domain routedomain; /* or at least forward */
1197
1198 static struct protosw routesw[] = {
1199 { SOCK_RAW, &routedomain, 0, PR_ATOMIC|PR_ADDR,
1200 0, route_output, raw_ctlinput, 0,
1201 0,
1202 raw_init, 0, 0, 0,
1203 &route_usrreqs
1204 }
1205 };
1206
1207 static struct domain routedomain =
1208 { PF_ROUTE, "route", 0, 0, 0,
1209 routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])] };
1210
1211 DOMAIN_SET(route);
Cache object: f3712cd58e79d26710809670b3041d13
|