revert between 56095 -> 55830 in arch
[AROS.git] / workbench / network / stacks / AROSTCP / bsdsocket / net / rtsock.c
blob40bbe80a197500b587c0a96c11af5b85d4ccd9f6
1 /*
2 * Copyright (C) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
3 * Helsinki University of Technology, Finland.
4 * All rights reserved.
5 * Copyright (C) 2005 - 2007 The AROS Dev Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
19 * MA 02111-1307, USA.
24 * Copyright (c) 1988, 1991 Regents of the University of California.
25 * All rights reserved.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
29 * are met:
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. All advertising materials mentioning features or use of this software
36 * must display the following acknowledgement:
37 * This product includes software developed by the University of
38 * California, Berkeley and its contributors.
39 * 4. Neither the name of the University nor the names of its contributors
40 * may be used to endorse or promote products derived from this software
41 * without specific prior written permission.
43 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 * SUCH DAMAGE.
55 * @(#)rtsock.c 7.18 (Berkeley) 6/27/91
58 #include <conf.h>
60 #include <sys/param.h>
61 #include <sys/malloc.h>
62 #include <sys/mbuf.h>
63 #include <sys/socket.h>
64 #include <sys/socketvar.h>
65 #include <sys/domain.h>
66 #include <sys/protosw.h>
67 #include <sys/synch.h>
69 #include <net/if.h>
70 #include <net/route.h>
71 #include <net/raw_cb.h>
73 #include <kern/amiga_subr.h>
75 #include <net/rtsock_protos.h>
76 #include <net/raw_usrreq_protos.h>
78 struct sockaddr route_dst = { 2, PF_ROUTE, };
79 struct sockaddr route_src = { 2, PF_ROUTE, };
80 struct sockproto route_proto = { PF_ROUTE, };
81 extern struct route_cb route_cb;
83 #define ROUNDUP(a) \
84 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
85 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
87 #ifndef AMITCP
89 route_usrreq(so, req, m, nam, control)
90 register struct socket *so;
91 int req;
92 struct mbuf *m, *nam, *control;
94 register int error = 0;
95 register struct rawcb *rp = sotorawcb(so);
96 spl_t s;
98 if (req == PRU_ATTACH) {
99 MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK);
100 if (so->so_pcb = (caddr_t)rp)
101 aligned_bzero_const(so->so_pcb, sizeof(*rp));
104 if (req == PRU_DETACH && rp) {
105 int af = rp->rcb_proto.sp_protocol;
106 if (af == AF_INET)
107 route_cb.ip_count--;
108 else if (af == AF_NS)
109 route_cb.ns_count--;
110 else if (af == AF_ISO)
111 route_cb.iso_count--;
112 route_cb.any_count--;
114 s = splnet();
115 error = raw_usrreq(so, req, m, nam, control);
116 rp = sotorawcb(so);
117 if (req == PRU_ATTACH && rp) {
118 int af = rp->rcb_proto.sp_protocol;
119 if (error) {
120 bsd_free((caddr_t)rp, M_PCB);
121 splx(s);
122 return (error);
124 if (af == AF_INET)
125 route_cb.ip_count++;
126 else if (af == AF_NS)
127 route_cb.ns_count++;
128 else if (af == AF_ISO)
129 route_cb.iso_count++;
130 rp->rcb_faddr = &route_src;
131 route_cb.any_count++;
132 soisconnected(so);
133 so->so_options |= SO_USELOOPBACK;
135 splx(s);
136 return (error);
139 int STKARGFUN
140 route_output(m, so)
141 register struct mbuf *m;
142 struct socket *so;
144 register struct rt_msghdr *rtm = 0;
145 register struct rtentry *rt = 0;
146 struct rtentry *saved_nrt = 0;
147 struct sockaddr *dst = 0, *gate = 0, *netmask = 0, *genmask = 0;
148 struct sockaddr *ifpaddr = 0, *ifaaddr = 0;
149 caddr_t cp, lim;
150 int len, error = 0;
151 struct ifnet *ifp = 0;
152 struct ifaddr *ifa = 0;
153 struct ifaddr *ifaof_ifpforaddr(), *ifa_ifwithroute();
154 #ifdef AMITCP
155 struct proc *curproc = (struct proc*)cthread_data(cthread_self());
156 #endif
158 #define senderr(e) { error = e; goto flush;}
159 if (m == 0 || m->m_len < sizeof(long))
160 return (ENOBUFS);
161 if ((m = m_pullup(m, sizeof(long))) == 0)
162 return (ENOBUFS);
163 if ((m->m_flags & M_PKTHDR) == 0)
164 panic("route_output");
165 len = m->m_pkthdr.len;
166 if (len < sizeof(*rtm) ||
167 len != mtod(m, struct rt_msghdr *)->rtm_msglen)
168 senderr(EINVAL);
169 R_Malloc(rtm, struct rt_msghdr *, len);
170 if (rtm == 0)
171 senderr(ENOBUFS);
172 m_copydata(m, 0, len, (caddr_t)rtm);
173 if (rtm->rtm_version != RTM_VERSION)
174 senderr(EPROTONOSUPPORT);
175 rtm->rtm_pid = (pid_t)FindTask(NULL);
176 lim = len + (caddr_t) rtm;
177 cp = (caddr_t) (rtm + 1);
178 if (rtm->rtm_addrs & RTA_DST) {
179 dst = (struct sockaddr *)cp;
180 ADVANCE(cp, dst);
181 } else
182 senderr(EINVAL);
183 if ((rtm->rtm_addrs & RTA_GATEWAY) && cp < lim) {
184 gate = (struct sockaddr *)cp;
185 ADVANCE(cp, gate);
187 if ((rtm->rtm_addrs & RTA_NETMASK) && cp < lim) {
188 netmask = (struct sockaddr *)cp;
189 ADVANCE(cp, netmask);
191 if ((rtm->rtm_addrs & RTA_GENMASK) && cp < lim) {
192 struct radix_node *t, *rn_addmask();
193 genmask = (struct sockaddr *)cp;
194 ADVANCE(cp, genmask);
195 t = rn_addmask(genmask, 1, 2);
196 if (t && Bcmp(genmask, t->rn_key, *(u_char *)genmask) == 0)
197 genmask = (struct sockaddr *)(t->rn_key);
198 else
199 senderr(ENOBUFS);
201 if ((rtm->rtm_addrs & RTA_IFP) && cp < lim) {
202 ifpaddr = (struct sockaddr *)cp;
203 ADVANCE(cp, ifpaddr);
205 if ((rtm->rtm_addrs & RTA_IFA) && cp < lim) {
206 ifaaddr = (struct sockaddr *)cp;
208 switch (rtm->rtm_type) {
209 case RTM_ADD:
210 if (gate == 0)
211 senderr(EINVAL);
212 error = rtrequest(RTM_ADD, dst, gate, netmask,
213 rtm->rtm_flags, &saved_nrt);
214 if (error == 0 && saved_nrt) {
215 rt_setmetrics(rtm->rtm_inits,
216 &rtm->rtm_rmx, &saved_nrt->rt_rmx);
217 saved_nrt->rt_refcnt--;
218 saved_nrt->rt_genmask = genmask;
220 break;
222 case RTM_DELETE:
223 error = rtrequest(RTM_DELETE, dst, gate, netmask,
224 rtm->rtm_flags, (struct rtentry **)0);
225 break;
227 case RTM_GET:
228 case RTM_CHANGE:
229 case RTM_LOCK:
230 rt = rtalloc1(dst, 0);
231 if (rt == 0)
232 senderr(ESRCH);
233 if (rtm->rtm_type != RTM_GET) {
234 if (Bcmp(dst, rt_key(rt), dst->sa_len) != 0)
235 senderr(ESRCH);
236 if (rt->rt_nodes->rn_dupedkey &&
237 (netmask == 0 ||
238 Bcmp(netmask, rt_mask(rt), netmask->sa_len)))
239 senderr(ETOOMANYREFS);
241 switch(rtm->rtm_type) {
243 case RTM_GET:
244 dst = rt_key(rt); len = sizeof(*rtm);
245 ADVANCE(len, dst);
246 rtm->rtm_addrs |= RTA_DST;
247 if (gate = rt->rt_gateway) {
248 ADVANCE(len, gate);
249 rtm->rtm_addrs |= RTA_GATEWAY;
250 } else
251 rtm->rtm_addrs &= ~RTA_GATEWAY;
252 if (netmask = rt_mask(rt)) {
253 ADVANCE(len, netmask);
254 rtm->rtm_addrs |= RTA_NETMASK;
255 } else
256 rtm->rtm_addrs &= ~RTA_NETMASK;
257 if (genmask = rt->rt_genmask) {
258 ADVANCE(len, genmask);
259 rtm->rtm_addrs |= RTA_GENMASK;
260 } else
261 rtm->rtm_addrs &= ~RTA_GENMASK;
262 if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
263 if (rt->rt_ifp == 0)
264 goto badif;
265 for (ifa = rt->rt_ifp->if_addrlist;
266 ifa && ifa->ifa_addr->sa_family != AF_LINK;
267 ifa = ifa->ifa_next){}
268 if (ifa && rt->rt_ifa) {
269 ifpaddr = ifa->ifa_addr;
270 ADVANCE(len, ifpaddr);
271 ifaaddr = rt->rt_ifa->ifa_addr;
272 ADVANCE(len, ifaaddr);
273 rtm->rtm_addrs |= RTA_IFP | RTA_IFA;
274 } else {
275 badif: ifpaddr = 0;
276 rtm->rtm_addrs &= ~(RTA_IFP | RTA_IFA);
279 if (len > rtm->rtm_msglen) {
280 struct rt_msghdr *new_rtm;
281 R_Malloc(new_rtm, struct rt_msghdr *, len);
282 if (new_rtm == 0)
283 senderr(ENOBUFS);
284 Bcopy(rtm, new_rtm, rtm->rtm_msglen);
285 Free(rtm); rtm = new_rtm;
287 rtm->rtm_msglen = len;
288 rtm->rtm_flags = rt->rt_flags;
289 rtm->rtm_rmx = rt->rt_rmx;
290 cp = (caddr_t) (1 + rtm);
291 len = ROUNDUP(dst->sa_len);
292 Bcopy(dst, cp, len); cp += len;
293 if (gate) {
294 len = ROUNDUP(gate->sa_len);
295 Bcopy(gate, cp, len); cp += len;
297 if (netmask) {
298 len = ROUNDUP(netmask->sa_len);
299 Bcopy(netmask, cp, len); cp += len;
301 if (genmask) {
302 len = ROUNDUP(genmask->sa_len);
303 Bcopy(genmask, cp, len); cp += len;
305 if (ifpaddr) {
306 len = ROUNDUP(ifpaddr->sa_len);
307 Bcopy(ifpaddr, cp, len); cp += len;
308 len = ROUNDUP(ifaaddr->sa_len);
309 Bcopy(ifaaddr, cp, len); cp += len;
311 break;
313 case RTM_CHANGE:
314 if (gate &&
315 (gate->sa_len > (len = rt->rt_gateway->sa_len)))
316 senderr(EDQUOT);
317 /* new gateway could require new ifaddr, ifp;
318 flags may also be different; ifp may be specified
319 by ll sockaddr when protocol address is ambiguous */
320 if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) &&
321 (ifp = ifa->ifa_ifp))
322 ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate,
323 ifp);
324 else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) ||
325 (ifa = ifa_ifwithroute(rt->rt_flags,
326 rt_key(rt), gate)))
327 ifp = ifa->ifa_ifp;
328 if (ifa) {
329 register struct ifaddr *oifa = rt->rt_ifa;
330 if (oifa != ifa) {
331 if (oifa && oifa->ifa_rtrequest)
332 oifa->ifa_rtrequest(RTM_DELETE,
333 rt, gate);
334 rt->rt_ifa = ifa;
335 rt->rt_ifp = ifp;
338 if (gate)
339 Bcopy(gate, rt->rt_gateway, len);
340 rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
341 &rt->rt_rmx);
342 if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
343 rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate);
344 if (genmask)
345 rt->rt_genmask = genmask;
347 * Fall into
349 case RTM_LOCK:
350 rt->rt_rmx.rmx_locks |=
351 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
352 rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
353 break;
355 goto cleanup;
357 default:
358 senderr(EOPNOTSUPP);
361 flush:
362 if (rtm) {
363 if (error)
364 rtm->rtm_errno = error;
365 else
366 rtm->rtm_flags |= RTF_DONE;
368 cleanup:
369 if (rt)
370 rtfree(rt);
372 register struct rawcb *rp = 0;
374 * Check to see if we don't want our own messages.
376 if ((so->so_options & SO_USELOOPBACK) == 0) {
377 if (route_cb.any_count <= 1) {
378 if (rtm)
379 Free(rtm);
380 m_freem(m);
381 return (error);
383 /* There is another listener, so construct message */
384 rp = sotorawcb(so);
386 if (rtm) {
387 m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
388 Free(rtm);
390 if (rp)
391 rp->rcb_proto.sp_family = 0; /* Avoid us */
392 if (dst)
393 route_proto.sp_protocol = dst->sa_family;
394 raw_input(m, &route_proto, &route_src, &route_dst);
395 if (rp)
396 rp->rcb_proto.sp_family = PF_ROUTE;
398 return (error);
400 #endif /* AMITCP */
402 void
403 rt_setmetrics(which, in, out)
404 u_long which;
405 register struct rt_metrics *in, *out;
407 #define metric(f, e) if (which & (f)) out->e = in->e;
408 metric(RTV_RPIPE, rmx_recvpipe);
409 metric(RTV_SPIPE, rmx_sendpipe);
410 metric(RTV_SSTHRESH, rmx_ssthresh);
411 metric(RTV_RTT, rmx_rtt);
412 metric(RTV_RTTVAR, rmx_rttvar);
413 metric(RTV_HOPCOUNT, rmx_hopcount);
414 metric(RTV_MTU, rmx_mtu);
415 metric(RTV_EXPIRE, rmx_expire);
416 #undef metric
420 * Copy data from a buffer back into the indicated mbuf chain,
421 * starting "off" bytes from the beginning, extending the mbuf
422 * chain if necessary.
424 void
425 m_copyback(m0, off, len, cp)
426 struct mbuf *m0;
427 register int off;
428 register int len;
429 caddr_t cp;
432 register int mlen;
433 register struct mbuf *m = m0, *n;
434 int totlen = 0;
436 if (m0 == 0)
437 return;
438 while (off > (mlen = m->m_len)) {
439 off -= mlen;
440 totlen += mlen;
441 if (m->m_next == 0) {
442 n = m_getclr(M_DONTWAIT, m->m_type);
443 if (n == 0)
444 goto out;
445 n->m_len = MIN(MLEN, len + off);
446 m->m_next = n;
448 m = m->m_next;
450 while (len > 0) {
451 mlen = MIN(m->m_len - off, len);
452 bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
453 cp += mlen;
454 len -= mlen;
455 mlen += off;
456 off = 0;
457 totlen += mlen;
458 if (len == 0)
459 break;
460 if (m->m_next == 0) {
461 n = m_get(M_DONTWAIT, m->m_type);
462 if (n == 0)
463 break;
464 n->m_len = MIN(MLEN, len);
465 m->m_next = n;
467 m = m->m_next;
469 out: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
470 m->m_pkthdr.len = totlen;
474 * The miss message and losing message are very similar.
477 void
478 rt_missmsg(type, dst, gate, mask, src, flags, error)
479 int type;
480 register struct sockaddr *dst;
481 struct sockaddr *gate, *mask, *src;
482 int flags;
483 int error;
485 register struct rt_msghdr *rtm;
486 register struct mbuf *m;
487 int dlen = ROUNDUP(dst->sa_len);
488 int len = dlen + sizeof(*rtm);
489 #ifndef AMITCP
490 struct proc *curproc = (struct proc*)cthread_data(cthread_self());
491 #endif /* AMITCP */
492 if (route_cb.any_count == 0)
493 return;
494 m = m_gethdr(M_DONTWAIT, MT_DATA);
495 if (m == 0)
496 return;
497 m->m_pkthdr.len = m->m_len = MIN(len, MHLEN);
498 m->m_pkthdr.rcvif = 0;
499 rtm = mtod(m, struct rt_msghdr *);
500 aligned_bzero_const((caddr_t)rtm, sizeof(*rtm)); /*XXX assumes sizeof(*rtm) < MHLEN*/
501 rtm->rtm_flags = RTF_DONE | flags;
502 rtm->rtm_msglen = len;
503 rtm->rtm_version = RTM_VERSION;
504 rtm->rtm_type = type;
505 rtm->rtm_addrs = RTA_DST;
506 if (type == RTM_OLDADD || type == RTM_OLDDEL) {
507 rtm->rtm_pid = (pid_t)FindTask(NULL);
509 m_copyback(m, sizeof (*rtm), dlen, (caddr_t)dst);
510 if (gate) {
511 dlen = ROUNDUP(gate->sa_len);
512 m_copyback(m, len , dlen, (caddr_t)gate);
513 len += dlen;
514 rtm->rtm_addrs |= RTA_GATEWAY;
516 if (mask) {
517 dlen = ROUNDUP(mask->sa_len);
518 m_copyback(m, len , dlen, (caddr_t)mask);
519 len += dlen;
520 rtm->rtm_addrs |= RTA_NETMASK;
522 if (src) {
523 dlen = ROUNDUP(src->sa_len);
524 m_copyback(m, len , dlen, (caddr_t)src);
525 len += dlen;
526 rtm->rtm_addrs |= RTA_AUTHOR;
528 if (m->m_pkthdr.len != len) {
529 m_freem(m);
530 return;
532 rtm->rtm_errno = error;
533 rtm->rtm_msglen = len;
534 route_proto.sp_protocol = dst->sa_family;
535 raw_input(m, &route_proto, &route_src, &route_dst);
539 #ifndef AMITCP /* this mechanism must be implemented differently */
540 #include <sys/kinfo.h>
541 struct walkarg {
542 int w_op, w_arg;
543 int w_given, w_needed;
544 caddr_t w_where;
545 struct {
546 struct rt_msghdr m_rtm;
547 char m_sabuf[128];
548 } w_m = 0;
549 #define w_rtm w_m.m_rtm
552 * This is used in dumping the kernel table via getkinfo().
554 rt_dumpentry(rn, w)
555 struct radix_node *rn;
556 register struct walkarg *w;
558 register struct sockaddr *sa;
559 int n, error;
561 for (; rn; rn = rn->rn_dupedkey) {
562 int count = 0, size = sizeof(w->w_rtm);
563 register struct rtentry *rt = (struct rtentry *)rn;
565 if (rn->rn_flags & RNF_ROOT)
566 continue;
567 if (w->w_op == KINFO_RT_FLAGS && !(rt->rt_flags & w->w_arg))
568 continue;
569 #define next(a, l) {size += (l); w->w_rtm.rtm_addrs |= (a); }
570 w->w_rtm.rtm_addrs = 0;
571 if (sa = rt_key(rt))
572 next(RTA_DST, ROUNDUP(sa->sa_len));
573 if (sa = rt->rt_gateway)
574 next(RTA_GATEWAY, ROUNDUP(sa->sa_len));
575 if (sa = rt_mask(rt))
576 next(RTA_NETMASK, ROUNDUP(sa->sa_len));
577 if (sa = rt->rt_genmask)
578 next(RTA_GENMASK, ROUNDUP(sa->sa_len));
579 w->w_needed += size;
580 if (w->w_where == NULL || w->w_needed > 0)
581 continue;
582 w->w_rtm.rtm_msglen = size;
583 w->w_rtm.rtm_flags = rt->rt_flags;
584 w->w_rtm.rtm_use = rt->rt_use;
585 w->w_rtm.rtm_rmx = rt->rt_rmx;
586 w->w_rtm.rtm_index = rt->rt_ifp->if_index;
587 #undef next
588 #define next(l) {n = (l); Bcopy(sa, cp, n); cp += n;}
589 if (size <= sizeof(w->w_m)) {
590 register caddr_t cp = (caddr_t)(w->w_m.m_sabuf);
591 if (sa = rt_key(rt))
592 next(ROUNDUP(sa->sa_len));
593 if (sa = rt->rt_gateway)
594 next(ROUNDUP(sa->sa_len));
595 if (sa = rt_mask(rt))
596 next(ROUNDUP(sa->sa_len));
597 if (sa = rt->rt_genmask)
598 next(ROUNDUP(sa->sa_len));
599 #undef next
600 #define next(s, l) {n = (l); \
601 if (error = copyout((caddr_t)(s), w->w_where, n)) return (error); \
602 w->w_where += n;}
604 next(&w->w_m, size); /* Copy rtmsg and sockaddrs back */
605 continue;
607 next(&w->w_rtm, sizeof(w->w_rtm));
608 if (sa = rt_key(rt))
609 next(sa, ROUNDUP(sa->sa_len));
610 if (sa = rt->rt_gateway)
611 next(sa, ROUNDUP(sa->sa_len));
612 if (sa = rt_mask(rt))
613 next(sa, ROUNDUP(sa->sa_len));
614 if (sa = rt->rt_genmask)
615 next(sa, ROUNDUP(sa->sa_len));
617 return (0);
618 #undef next
621 kinfo_rtable(op, where, given, arg, needed)
622 int op, arg;
623 caddr_t where;
624 int *given, *needed;
626 register struct radix_node_head *rnh;
627 int error = 0;
628 spl_t s;
629 u_char af = ki_af(op);
630 struct walkarg w;
632 op &= 0xffff;
633 if (op != KINFO_RT_DUMP && op != KINFO_RT_FLAGS)
634 return (EINVAL);
636 Bzero(&w, sizeof(w));
637 if ((w.w_where = where) && given)
638 w.w_given = *given;
639 w.w_needed = 0 - w.w_given;
640 w.w_arg = arg;
641 w.w_op = op;
642 w.w_rtm.rtm_version = RTM_VERSION;
643 w.w_rtm.rtm_type = RTM_GET;
645 s = splnet();
646 for (rnh = radix_node_head; rnh; rnh = rnh->rnh_next) {
647 if (rnh->rnh_af == 0)
648 continue;
649 if (af && af != rnh->rnh_af)
650 continue;
651 error = rt_walk(rnh->rnh_treetop, rt_dumpentry, &w);
652 if (error)
653 break;
655 w.w_needed += w.w_given;
656 if (where && given)
657 *given = w.w_where - where;
658 else
659 w.w_needed = (11 * w.w_needed) / 10;
660 *needed = w.w_needed;
661 splx(s);
662 return (error);
664 #endif /* AMITCP */
667 rt_walk(rn, f, w)
668 register struct radix_node *rn;
669 register int (*f)(struct radix_node *, struct walkarg *);
670 struct walkarg *w;
672 int error;
673 for (;;) {
674 while (rn->rn_b >= 0)
675 rn = rn->rn_l; /* First time through node, go left */
676 if (error = (*f)(rn, w))
677 return (error); /* Process Leaf */
678 while (rn->rn_p->rn_r == rn) { /* if coming back from right */
679 rn = rn->rn_p; /* go back up */
680 if (rn->rn_flags & RNF_ROOT)
681 return 0;
683 rn = rn->rn_p->rn_r; /* otherwise, go right*/
688 * Definitions of protocols supported in the ROUTE domain.
690 #ifdef AMITCP
692 * Actually, we are only initializing the raw control blocks...
694 #define route_output NULL
695 #define route_usrreq NULL
696 #else /* AMITCP */
697 int raw_init(),raw_usrreq(),raw_input(),raw_ctlinput();
698 #endif /* AMITCP */
699 extern struct domain routedomain; /* or at least forward */
701 struct protosw routesw[] = {
702 { SOCK_RAW, &routedomain, 0, PR_ATOMIC|PR_ADDR,
703 (void (*)(APTR args, ...))raw_input, route_output, (APTR)raw_ctlinput, 0,
704 route_usrreq,
705 raw_init, 0, 0, 0,
709 int unp_externalize(), unp_dispose();
711 struct domain routedomain =
712 { PF_ROUTE, "route", NULL, NULL, NULL,
713 routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])], NULL };