URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
Compare Revisions
- This comparison shows the changes necessary to convert path
/openrisc/trunk/rtos/rtems/c/src/libnetworking/net
- from Rev 30 to Rev 173
- ↔ Reverse comparison
Rev 30 → Rev 173
/route.c
0,0 → 1,959
/* |
* Copyright (c) 1980, 1986, 1991, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)route.c 8.2 (Berkeley) 11/15/93 |
* $Id: route.c,v 1.2 2001-09-27 12:01:54 chris Exp $ |
*/ |
|
#include "opt_mrouting.h" |
|
#include <sys/param.h> |
#include <sys/queue.h> |
#include <sys/systm.h> |
#include <sys/kernel.h> |
#include <sys/proc.h> |
#include <sys/mbuf.h> |
#include <sys/socket.h> |
#include <sys/socketvar.h> |
#include <sys/domain.h> |
#include <sys/protosw.h> |
#include <sys/ioctl.h> |
|
#include <net/if.h> |
#include <net/route.h> |
#include <net/raw_cb.h> |
|
#include <netinet/in.h> |
#include <netinet/in_var.h> |
#include <netinet/ip_mroute.h> |
|
#define SA(p) ((struct sockaddr *)(p)) |
|
struct route_cb route_cb; |
static struct rtstat rtstat; |
struct radix_node_head *rt_tables[AF_MAX+1]; |
|
static int rttrash; /* routes not in table but not freed */ |
|
static void rt_maskedcopy __P((struct sockaddr *, |
struct sockaddr *, struct sockaddr *)); |
static void rtable_init __P((void **)); |
|
static void |
rtable_init(table) |
void **table; |
{ |
struct domain *dom; |
for (dom = domains; dom; dom = dom->dom_next) |
if (dom->dom_rtattach) |
dom->dom_rtattach(&table[dom->dom_family], |
dom->dom_rtoffset); |
} |
|
void |
route_init() |
{ |
rn_init(); /* initialize all zeroes, all ones, mask table */ |
rtable_init((void **)rt_tables); |
} |
|
/* |
* Packet routing routines. |
*/ |
void |
rtalloc(ro) |
register struct route *ro; |
{ |
if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP)) |
return; /* XXX */ |
ro->ro_rt = rtalloc1(&ro->ro_dst, 1, 0UL); |
} |
|
void |
rtalloc_ign(ro, ignore) |
register struct route *ro; |
u_long ignore; |
{ |
if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP)) |
return; /* XXX */ |
ro->ro_rt = rtalloc1(&ro->ro_dst, 1, ignore); |
} |
|
/* |
* Look up the route that matches the address given |
* Or, at least try.. Create a cloned route if needed. |
*/ |
struct rtentry * |
rtalloc1(dst, report, ignflags) |
register struct sockaddr *dst; |
int report; |
u_long ignflags; |
{ |
register struct radix_node_head *rnh = rt_tables[dst->sa_family]; |
register struct rtentry *rt; |
register struct radix_node *rn; |
struct rtentry *newrt = 0; |
struct rt_addrinfo info; |
u_long nflags; |
int s = splnet(), err = 0, msgtype = RTM_MISS; |
|
/* |
* Look up the address in the table for that Address Family |
*/ |
if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) && |
((rn->rn_flags & RNF_ROOT) == 0)) { |
/* |
* If we find it and it's not the root node, then |
* get a refernce on the rtentry associated. |
*/ |
newrt = rt = (struct rtentry *)rn; |
nflags = rt->rt_flags & ~ignflags; |
if (report && (nflags & (RTF_CLONING | RTF_PRCLONING))) { |
/* |
* We are apparently adding (report = 0 in delete). |
* If it requires that it be cloned, do so. |
* (This implies it wasn't a HOST route.) |
*/ |
err = rtrequest(RTM_RESOLVE, dst, SA(0), |
SA(0), 0, &newrt); |
if (err) { |
/* |
* If the cloning didn't succeed, maybe |
* what we have will do. Return that. |
*/ |
newrt = rt; |
rt->rt_refcnt++; |
goto miss; |
} |
if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) { |
/* |
* If the new route specifies it be |
* externally resolved, then go do that. |
*/ |
msgtype = RTM_RESOLVE; |
goto miss; |
} |
} else |
rt->rt_refcnt++; |
} else { |
/* |
* Either we hit the root or couldn't find any match, |
* Which basically means |
* "caint get there frm here" |
*/ |
rtstat.rts_unreach++; |
miss: if (report) { |
/* |
* If required, report the failure to the supervising |
* Authorities. |
* For a delete, this is not an error. (report == 0) |
*/ |
bzero((caddr_t)&info, sizeof(info)); |
info.rti_info[RTAX_DST] = dst; |
rt_missmsg(msgtype, &info, 0, err); |
} |
} |
splx(s); |
return (newrt); |
} |
|
void |
rtfree(rt) |
register struct rtentry *rt; |
{ |
register struct radix_node_head *rnh = |
rt_tables[rt_key(rt)->sa_family]; |
register struct ifaddr *ifa; |
|
if (rt == 0 || rnh == 0) |
panic("rtfree"); |
rt->rt_refcnt--; |
if(rnh->rnh_close && rt->rt_refcnt == 0) { |
rnh->rnh_close((struct radix_node *)rt, rnh); |
} |
if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_UP) == 0) { |
if (rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT)) |
panic ("rtfree 2"); |
rttrash--; |
if (rt->rt_refcnt < 0) { |
printf("rtfree: %p not freed (neg refs)\n", rt); |
return; |
} |
ifa = rt->rt_ifa; |
IFAFREE(ifa); |
if (rt->rt_parent) { |
RTFREE(rt->rt_parent); |
} |
Free(rt_key(rt)); |
Free(rt); |
} |
} |
|
void |
ifafree(ifa) |
register struct ifaddr *ifa; |
{ |
if (ifa == NULL) |
panic("ifafree"); |
if (ifa->ifa_refcnt == 0) |
free(ifa, M_IFADDR); |
else |
ifa->ifa_refcnt--; |
} |
|
/* |
* Force a routing table entry to the specified |
* destination to go through the given gateway. |
* Normally called as a result of a routing redirect |
* message from the network layer. |
* |
* N.B.: must be called at splnet |
* |
*/ |
void |
rtredirect(dst, gateway, netmask, flags, src, rtp) |
struct sockaddr *dst, *gateway, *netmask, *src; |
int flags; |
struct rtentry **rtp; |
{ |
register struct rtentry *rt; |
int error = 0; |
short *stat = 0; |
struct rt_addrinfo info; |
struct ifaddr *ifa; |
|
/* verify the gateway is directly reachable */ |
if ((ifa = ifa_ifwithnet(gateway)) == 0) { |
error = ENETUNREACH; |
goto out; |
} |
rt = rtalloc1(dst, 0, 0UL); |
/* |
* If the redirect isn't from our current router for this dst, |
* it's either old or wrong. If it redirects us to ourselves, |
* we have a routing loop, perhaps as a result of an interface |
* going down recently. |
*/ |
#define equal(a1, a2) (bcmp((caddr_t)(a1), (caddr_t)(a2), (a1)->sa_len) == 0) |
if (!(flags & RTF_DONE) && rt && |
(!equal(src, rt->rt_gateway) || rt->rt_ifa != ifa)) |
error = EINVAL; |
else if (ifa_ifwithaddr(gateway)) |
error = EHOSTUNREACH; |
if (error) |
goto done; |
/* |
* Create a new entry if we just got back a wildcard entry |
* or the the lookup failed. This is necessary for hosts |
* which use routing redirects generated by smart gateways |
* to dynamically build the routing tables. |
*/ |
if ((rt == 0) || (rt_mask(rt) && rt_mask(rt)->sa_len < 2)) |
goto create; |
/* |
* Don't listen to the redirect if it's |
* for a route to an interface. |
*/ |
if (rt->rt_flags & RTF_GATEWAY) { |
if (((rt->rt_flags & RTF_HOST) == 0) && (flags & RTF_HOST)) { |
/* |
* Changing from route to net => route to host. |
* Create new route, rather than smashing route to net. |
*/ |
create: |
flags |= RTF_GATEWAY | RTF_DYNAMIC; |
error = rtrequest((int)RTM_ADD, dst, gateway, |
netmask, flags, |
(struct rtentry **)0); |
stat = &rtstat.rts_dynamic; |
} else { |
/* |
* Smash the current notion of the gateway to |
* this destination. Should check about netmask!!! |
*/ |
rt->rt_flags |= RTF_MODIFIED; |
flags |= RTF_MODIFIED; |
stat = &rtstat.rts_newgateway; |
rt_setgate(rt, rt_key(rt), gateway); |
} |
} else |
error = EHOSTUNREACH; |
done: |
if (rt) { |
if (rtp && !error) |
*rtp = rt; |
else |
rtfree(rt); |
} |
out: |
if (error) |
rtstat.rts_badredirect++; |
else if (stat != NULL) |
(*stat)++; |
bzero((caddr_t)&info, sizeof(info)); |
info.rti_info[RTAX_DST] = dst; |
info.rti_info[RTAX_GATEWAY] = gateway; |
info.rti_info[RTAX_NETMASK] = netmask; |
info.rti_info[RTAX_AUTHOR] = src; |
rt_missmsg(RTM_REDIRECT, &info, flags, error); |
} |
|
/* |
* Routing table ioctl interface. |
*/ |
int |
rtioctl(req, data, p) |
int req; |
caddr_t data; |
struct proc *p; |
{ |
#ifdef INET |
/* Multicast goop, grrr... */ |
#ifdef MROUTING |
return mrt_ioctl(req, data); |
#else |
return mrt_ioctl(req, data, p); |
#endif |
#else /* INET */ |
return ENXIO; |
#endif /* INET */ |
} |
|
struct ifaddr * |
ifa_ifwithroute(flags, dst, gateway) |
int flags; |
struct sockaddr *dst, *gateway; |
{ |
register struct ifaddr *ifa; |
if ((flags & RTF_GATEWAY) == 0) { |
/* |
* If we are adding a route to an interface, |
* and the interface is a pt to pt link |
* we should search for the destination |
* as our clue to the interface. Otherwise |
* we can use the local address. |
*/ |
ifa = 0; |
if (flags & RTF_HOST) { |
ifa = ifa_ifwithdstaddr(dst); |
} |
if (ifa == 0) |
ifa = ifa_ifwithaddr(gateway); |
} else { |
/* |
* If we are adding a route to a remote net |
* or host, the gateway may still be on the |
* other end of a pt to pt link. |
*/ |
ifa = ifa_ifwithdstaddr(gateway); |
} |
if (ifa == 0) |
ifa = ifa_ifwithnet(gateway); |
if (ifa == 0) { |
struct rtentry *rt = rtalloc1(dst, 0, 0UL); |
if (rt == 0) |
return (0); |
rt->rt_refcnt--; |
if ((ifa = rt->rt_ifa) == 0) |
return (0); |
} |
if (ifa->ifa_addr->sa_family != dst->sa_family) { |
struct ifaddr *oifa = ifa; |
ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp); |
if (ifa == 0) |
ifa = oifa; |
} |
return (ifa); |
} |
|
#define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) |
|
static int rt_fixdelete(struct radix_node *, void *); |
static int rt_fixchange(struct radix_node *, void *); |
|
struct rtfc_arg { |
struct rtentry *rt0; |
struct radix_node_head *rnh; |
}; |
|
/* |
* Do appropriate manipulations of a routing tree given |
* all the bits of info needed |
*/ |
int |
rtrequest(req, dst, gateway, netmask, flags, ret_nrt) |
int req, flags; |
struct sockaddr *dst, *gateway, *netmask; |
struct rtentry **ret_nrt; |
{ |
int s = splnet(); int error = 0; |
register struct rtentry *rt; |
register struct radix_node *rn; |
register struct radix_node_head *rnh; |
struct ifaddr *ifa; |
struct sockaddr *ndst; |
#define senderr(x) { error = x ; goto bad; } |
|
/* |
* Find the correct routing tree to use for this Address Family |
*/ |
if ((rnh = rt_tables[dst->sa_family]) == 0) |
senderr(ESRCH); |
/* |
* If we are adding a host route then we don't want to put |
* a netmask in the tree |
*/ |
if (flags & RTF_HOST) |
netmask = 0; |
switch (req) { |
case RTM_DELETE: |
/* |
* Remove the item from the tree and return it. |
* Complain if it is not there and do no more processing. |
*/ |
if ((rn = rnh->rnh_deladdr(dst, netmask, rnh)) == 0) |
senderr(ESRCH); |
if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT)) |
panic ("rtrequest delete"); |
rt = (struct rtentry *)rn; |
|
/* |
* Now search what's left of the subtree for any cloned |
* routes which might have been formed from this node. |
*/ |
if ((rt->rt_flags & RTF_PRCLONING) && netmask) { |
rnh->rnh_walktree_from(rnh, dst, netmask, |
rt_fixdelete, rt); |
} |
|
/* |
* Remove any external references we may have. |
* This might result in another rtentry being freed if |
* we held it's last reference. |
*/ |
if (rt->rt_gwroute) { |
rt = rt->rt_gwroute; |
RTFREE(rt); |
(rt = (struct rtentry *)rn)->rt_gwroute = 0; |
} |
|
/* |
* NB: RTF_UP must be set during the search above, |
* because we might delete the last ref, causing |
* rt to get freed prematurely. |
*/ |
rt->rt_flags &= ~RTF_UP; |
|
/* |
* If there is llinfo or similar associated with the |
* route, give the interface a chance to deal with it.. |
*/ |
if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest) |
ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0)); |
rttrash++; |
/* |
* If the caller wants it, then it can have it, but it's up to it |
* to free the rtentry as we won't be doing it. |
*/ |
if (ret_nrt) |
*ret_nrt = rt; |
else if (rt->rt_refcnt <= 0) { |
rt->rt_refcnt++; /* make a 1->0 transition */ |
rtfree(rt); |
} |
break; |
|
case RTM_RESOLVE: |
if (ret_nrt == 0 || (rt = *ret_nrt) == 0) |
senderr(EINVAL); |
ifa = rt->rt_ifa; |
flags = rt->rt_flags & |
~(RTF_CLONING | RTF_PRCLONING | RTF_STATIC); |
flags |= RTF_WASCLONED; |
gateway = rt->rt_gateway; |
if ((netmask = rt->rt_genmask) == 0) |
flags |= RTF_HOST; |
goto makeroute; |
|
case RTM_ADD: |
if ((flags & RTF_GATEWAY) && !gateway) |
panic("rtrequest: GATEWAY but no gateway"); |
|
if ((ifa = ifa_ifwithroute(flags, dst, gateway)) == 0) |
senderr(ENETUNREACH); |
|
makeroute: |
R_Malloc(rt, struct rtentry *, sizeof(*rt)); |
if (rt == 0) |
senderr(ENOBUFS); |
Bzero(rt, sizeof(*rt)); |
rt->rt_flags = RTF_UP | flags; |
if ((error = rt_setgate(rt, dst, gateway))) { |
Free(rt); |
senderr(error); |
} |
ndst = rt_key(rt); |
if (netmask) { |
rt_maskedcopy(dst, ndst, netmask); |
} else |
Bcopy(dst, ndst, dst->sa_len); |
|
/* |
* This moved from below so that rnh->rnh_addaddr() can |
* examine the ifa and ifp if it so desires. |
*/ |
ifa->ifa_refcnt++; |
rt->rt_ifa = ifa; |
rt->rt_ifp = ifa->ifa_ifp; |
|
rn = rnh->rnh_addaddr((caddr_t)ndst, (caddr_t)netmask, |
rnh, rt->rt_nodes); |
if (rn == 0) { |
struct rtentry *rt2; |
/* |
* Uh-oh, we already have one of these in the tree. |
* We do a special hack: if the route that's already |
* there was generated by the protocol-cloning |
* mechanism, then we just blow it away and retry |
* the insertion of the new one. |
*/ |
rt2 = rtalloc1(dst, 0, RTF_PRCLONING); |
if (rt2 && rt2->rt_parent) { |
rtrequest(RTM_DELETE, |
(struct sockaddr *)rt_key(rt2), |
rt2->rt_gateway, |
rt_mask(rt2), rt2->rt_flags, 0); |
RTFREE(rt2); |
rn = rnh->rnh_addaddr((caddr_t)ndst, |
(caddr_t)netmask, |
rnh, rt->rt_nodes); |
} else if (rt2) { |
RTFREE(rt2); |
} |
} |
|
if (rn == 0) { |
if (rt->rt_gwroute) |
rtfree(rt->rt_gwroute); |
if (rt->rt_ifa) { |
IFAFREE(rt->rt_ifa); |
} |
Free(rt_key(rt)); |
Free(rt); |
senderr(EEXIST); |
} |
rt->rt_parent = 0; |
|
if (req == RTM_RESOLVE) { |
rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */ |
if ((*ret_nrt)->rt_flags & RTF_PRCLONING) { |
rt->rt_parent = (*ret_nrt); |
(*ret_nrt)->rt_refcnt++; |
} |
} |
if (ifa->ifa_rtrequest) |
ifa->ifa_rtrequest(req, rt, SA(ret_nrt ? *ret_nrt : 0)); |
/* |
* We repeat the same procedure from rt_setgate() here because |
* it doesn't fire when we call it there because the node |
* hasn't been added to the tree yet. |
*/ |
if (!(rt->rt_flags & RTF_HOST) && rt_mask(rt) != 0) { |
struct rtfc_arg arg; |
arg.rnh = rnh; |
arg.rt0 = rt; |
rnh->rnh_walktree_from(rnh, rt_key(rt), rt_mask(rt), |
rt_fixchange, &arg); |
} |
|
if (ret_nrt) { |
*ret_nrt = rt; |
rt->rt_refcnt++; |
} |
break; |
} |
bad: |
splx(s); |
return (error); |
} |
|
/* |
* Called from rtrequest(RTM_DELETE, ...) to fix up the route's ``family'' |
* (i.e., the routes related to it by the operation of cloning). This |
* routine is iterated over all potential former-child-routes by way of |
* rnh->rnh_walktree_from() above, and those that actually are children of |
* the late parent (passed in as VP here) are themselves deleted. |
*/ |
static int |
rt_fixdelete(struct radix_node *rn, void *vp) |
{ |
struct rtentry *rt = (struct rtentry *)rn; |
struct rtentry *rt0 = vp; |
|
if (rt->rt_parent == rt0 && !(rt->rt_flags & RTF_PINNED)) { |
return rtrequest(RTM_DELETE, rt_key(rt), |
(struct sockaddr *)0, rt_mask(rt), |
rt->rt_flags, (struct rtentry **)0); |
} |
return 0; |
} |
|
/* |
* This routine is called from rt_setgate() to do the analogous thing for |
* adds and changes. There is the added complication in this case of a |
* middle insert; i.e., insertion of a new network route between an older |
* network route and (cloned) host routes. For this reason, a simple check |
* of rt->rt_parent is insufficient; each candidate route must be tested |
* against the (mask, value) of the new route (passed as before in vp) |
* to see if the new route matches it. Unfortunately, this has the obnoxious |
* property of also triggering for insertion /above/ a pre-existing network |
* route and clones. Sigh. This may be fixed some day. |
* |
* XXX - it may be possible to do fixdelete() for changes and reserve this |
* routine just for adds. I'm not sure why I thought it was necessary to do |
* changes this way. |
*/ |
#ifdef DEBUG |
int rtfcdebug = 0; |
#endif |
|
static int |
rt_fixchange(struct radix_node *rn, void *vp) |
{ |
struct rtentry *rt = (struct rtentry *)rn; |
struct rtfc_arg *ap = vp; |
struct rtentry *rt0 = ap->rt0; |
struct radix_node_head *rnh = ap->rnh; |
u_char *xk1, *xm1, *xk2; |
int i, len; |
|
#ifdef DEBUG |
if (rtfcdebug) |
printf("rt_fixchange: rt %p, rt0 %p\n", rt, rt0); |
#endif |
|
if (!rt->rt_parent || (rt->rt_flags & RTF_PINNED)) { |
#ifdef DEBUG |
if(rtfcdebug) printf("no parent or pinned\n"); |
#endif |
return 0; |
} |
|
if (rt->rt_parent == rt0) { |
#ifdef DEBUG |
if(rtfcdebug) printf("parent match\n"); |
#endif |
return rtrequest(RTM_DELETE, rt_key(rt), |
(struct sockaddr *)0, rt_mask(rt), |
rt->rt_flags, (struct rtentry **)0); |
} |
|
/* |
* There probably is a function somewhere which does this... |
* if not, there should be. |
*/ |
len = imin(((struct sockaddr *)rt_key(rt0))->sa_len, |
((struct sockaddr *)rt_key(rt))->sa_len); |
|
xk1 = (u_char *)rt_key(rt0); |
xm1 = (u_char *)rt_mask(rt0); |
xk2 = (u_char *)rt_key(rt); |
|
for (i = rnh->rnh_treetop->rn_off; i < len; i++) { |
if ((xk2[i] & xm1[i]) != xk1[i]) { |
#ifdef DEBUG |
if(rtfcdebug) printf("no match\n"); |
#endif |
return 0; |
} |
} |
|
/* |
* OK, this node is a clone, and matches the node currently being |
* changed/added under the node's mask. So, get rid of it. |
*/ |
#ifdef DEBUG |
if(rtfcdebug) printf("deleting\n"); |
#endif |
return rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0, |
rt_mask(rt), rt->rt_flags, (struct rtentry **)0); |
} |
|
int |
rt_setgate(rt0, dst, gate) |
struct rtentry *rt0; |
struct sockaddr *dst, *gate; |
{ |
caddr_t new, old; |
int dlen = ROUNDUP(dst->sa_len), glen = ROUNDUP(gate->sa_len); |
register struct rtentry *rt = rt0; |
struct radix_node_head *rnh = rt_tables[dst->sa_family]; |
|
/* |
* A host route with the destination equal to the gateway |
* will interfere with keeping LLINFO in the routing |
* table, so disallow it. |
*/ |
if (((rt0->rt_flags & (RTF_HOST|RTF_GATEWAY|RTF_LLINFO)) == |
(RTF_HOST|RTF_GATEWAY)) && |
(dst->sa_len == gate->sa_len) && |
(bcmp(dst, gate, dst->sa_len) == 0)) { |
/* |
* The route might already exist if this is an RTM_CHANGE |
* or a routing redirect, so try to delete it. |
*/ |
if (rt_key(rt0)) |
rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt0), |
rt0->rt_gateway, rt_mask(rt0), rt0->rt_flags, 0); |
return EADDRNOTAVAIL; |
} |
|
if (rt->rt_gateway == 0 || glen > ROUNDUP(rt->rt_gateway->sa_len)) { |
old = (caddr_t)rt_key(rt); |
R_Malloc(new, caddr_t, dlen + glen); |
if (new == 0) |
return ENOBUFS; |
rt->rt_nodes->rn_key = new; |
} else { |
new = rt->rt_nodes->rn_key; |
old = 0; |
} |
Bcopy(gate, (rt->rt_gateway = (struct sockaddr *)(new + dlen)), glen); |
if (old) { |
Bcopy(dst, new, dlen); |
Free(old); |
} |
if (rt->rt_gwroute) { |
rt = rt->rt_gwroute; RTFREE(rt); |
rt = rt0; rt->rt_gwroute = 0; |
} |
/* |
* Cloning loop avoidance: |
* In the presence of protocol-cloning and bad configuration, |
* it is possible to get stuck in bottomless mutual recursion |
* (rtrequest rt_setgate rtalloc1). We avoid this by not allowing |
* protocol-cloning to operate for gateways (which is probably the |
* correct choice anyway), and avoid the resulting reference loops |
* by disallowing any route to run through itself as a gateway. |
* This is obviuosly mandatory when we get rt->rt_output(). |
*/ |
if (rt->rt_flags & RTF_GATEWAY) { |
rt->rt_gwroute = rtalloc1(gate, 1, RTF_PRCLONING); |
if (rt->rt_gwroute == rt) { |
RTFREE(rt->rt_gwroute); |
rt->rt_gwroute = 0; |
return EDQUOT; /* failure */ |
} |
} |
|
/* |
* This isn't going to do anything useful for host routes, so |
* don't bother. Also make sure we have a reasonable mask |
* (we don't yet have one during adds). |
*/ |
if (!(rt->rt_flags & RTF_HOST) && rt_mask(rt) != 0) { |
struct rtfc_arg arg; |
arg.rnh = rnh; |
arg.rt0 = rt; |
rnh->rnh_walktree_from(rnh, rt_key(rt), rt_mask(rt), |
rt_fixchange, &arg); |
} |
|
return 0; |
} |
|
static void |
rt_maskedcopy(src, dst, netmask) |
struct sockaddr *src, *dst, *netmask; |
{ |
register u_char *cp1 = (u_char *)src; |
register u_char *cp2 = (u_char *)dst; |
register u_char *cp3 = (u_char *)netmask; |
u_char *cplim = cp2 + *cp3; |
u_char *cplim2 = cp2 + *cp1; |
|
*cp2++ = *cp1++; *cp2++ = *cp1++; /* copies sa_len & sa_family */ |
cp3 += 2; |
if (cplim > cplim2) |
cplim = cplim2; |
while (cp2 < cplim) |
*cp2++ = *cp1++ & *cp3++; |
if (cp2 < cplim2) |
bzero((caddr_t)cp2, (unsigned)(cplim2 - cp2)); |
} |
|
/* |
* Set up a routing table entry, normally |
* for an interface. |
*/ |
int |
rtinit(ifa, cmd, flags) |
register struct ifaddr *ifa; |
int cmd, flags; |
{ |
register struct rtentry *rt; |
register struct sockaddr *dst; |
register struct sockaddr *deldst; |
struct mbuf *m = 0; |
struct rtentry *nrt = 0; |
int error; |
|
dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr; |
/* |
* If it's a delete, check that if it exists, it's on the correct |
* interface or we might scrub a route to another ifa which would |
* be confusing at best and possibly worse. |
*/ |
if (cmd == RTM_DELETE) { |
/* |
* It's a delete, so it should already exist.. |
* If it's a net, mask off the host bits |
* (Assuming we have a mask) |
*/ |
if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) { |
m = m_get(M_WAIT, MT_SONAME); |
deldst = mtod(m, struct sockaddr *); |
rt_maskedcopy(dst, deldst, ifa->ifa_netmask); |
dst = deldst; |
} |
/* |
* Get an rtentry that is in the routing tree and |
* contains the correct info. (if this fails we can't get there). |
* We set "report" to FALSE so that if it doesn't exist, |
* it doesn't report an error or clone a route, etc. etc. |
*/ |
rt = rtalloc1(dst, 0, 0UL); |
if (rt) { |
/* |
* Ok so we found the rtentry. it has an extra reference |
* for us at this stage. we won't need that so |
* lop that off now. |
*/ |
rt->rt_refcnt--; |
if (rt->rt_ifa != ifa) { |
/* |
* If the interface in the rtentry doesn't match |
* the interface we are using, then we don't |
* want to delete it, so return an error. |
* This seems to be the only point of |
* this whole RTM_DELETE clause. |
*/ |
if (m) |
(void) m_free(m); |
return (flags & RTF_HOST ? EHOSTUNREACH |
: ENETUNREACH); |
} |
} |
/* XXX */ |
#if 0 |
else { |
/* |
* One would think that as we are deleting, and we know |
* it doesn't exist, we could just return at this point |
* with an "ELSE" clause, but apparently not.. |
*/ |
return (flags & RTF_HOST ? EHOSTUNREACH |
: ENETUNREACH); |
} |
#endif |
} |
/* |
* Do the actual request |
*/ |
error = rtrequest(cmd, dst, ifa->ifa_addr, ifa->ifa_netmask, |
flags | ifa->ifa_flags, &nrt); |
if (m) |
(void) m_free(m); |
/* |
* If we are deleting, and we found an entry, then |
* it's been removed from the tree.. now throw it away. |
*/ |
if (cmd == RTM_DELETE && error == 0 && (rt = nrt)) { |
/* |
* notify any listenning routing agents of the change |
*/ |
rt_newaddrmsg(cmd, ifa, error, nrt); |
if (rt->rt_refcnt <= 0) { |
rt->rt_refcnt++; /* need a 1->0 transition to free */ |
rtfree(rt); |
} |
} |
|
/* |
* We are adding, and we have a returned routing entry. |
* We need to sanity check the result. |
*/ |
if (cmd == RTM_ADD && error == 0 && (rt = nrt)) { |
/* |
* We just wanted to add it.. we don't actually need a reference |
*/ |
rt->rt_refcnt--; |
/* |
* If it came back with an unexpected interface, then it must |
* have already existed or something. (XXX) |
*/ |
if (rt->rt_ifa != ifa) { |
printf("rtinit: wrong ifa (%p) was (%p)\n", ifa, |
rt->rt_ifa); |
/* |
* Ask that the route we got back be removed |
* from the routing tables as we are trying |
* to supersede it. |
*/ |
if (rt->rt_ifa->ifa_rtrequest) |
rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0)); |
/* |
* Remove the referenve to the it's ifaddr. |
*/ |
IFAFREE(rt->rt_ifa); |
/* |
* And substitute in references to the ifaddr |
* we are adding. |
*/ |
rt->rt_ifa = ifa; |
rt->rt_ifp = ifa->ifa_ifp; |
ifa->ifa_refcnt++; |
/* |
* Now add it to the routing table |
* XXX could we have just left it? |
* as it might have been in the right place.. |
*/ |
if (ifa->ifa_rtrequest) |
ifa->ifa_rtrequest(RTM_ADD, rt, SA(0)); |
} |
/* |
* notify any listenning routing agents of the change |
*/ |
rt_newaddrmsg(cmd, ifa, error, nrt); |
} |
return (error); |
} |
/if.c
0,0 → 1,794
/* |
* Copyright (c) 1980, 1986, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)if.c 8.3 (Berkeley) 1/4/94 |
* $Id: if.c,v 1.2 2001-09-27 12:01:54 chris Exp $ |
*/ |
|
#include <sys/param.h> |
#include <sys/queue.h> |
#include <sys/mbuf.h> |
#include <sys/systm.h> |
#include <sys/proc.h> |
#include <sys/socket.h> |
#include <sys/socketvar.h> |
#include <sys/protosw.h> |
#include <sys/kernel.h> |
#include <sys/ioctl.h> |
#include <sys/errno.h> |
#include <sys/syslog.h> |
#include <sys/sysctl.h> |
|
#include <net/if.h> |
#include <net/if_dl.h> |
#include <net/if_types.h> |
#include <net/radix.h> |
|
/* |
* System initialization |
*/ |
|
static int ifconf __P((int, caddr_t)); |
void ifinit __P((void *)); |
static void if_qflush __P((struct ifqueue *)); |
static void if_slowtimo __P((void *)); |
static void link_rtrequest __P((int, struct rtentry *, struct sockaddr *)); |
|
SYSINIT(interfaces, SI_SUB_PROTO_IF, SI_ORDER_FIRST, ifinit, NULL) |
|
|
int ifqmaxlen = IFQ_MAXLEN; |
struct ifnet *ifnet; |
|
/* |
* Network interface utility routines. |
* |
* Routines with ifa_ifwith* names take sockaddr *'s as |
* parameters. |
* |
* This routine assumes that it will be called at splimp() or higher. |
*/ |
/* ARGSUSED*/ |
void |
ifinit(dummy) |
void *dummy; |
{ |
register struct ifnet *ifp; |
|
for (ifp = ifnet; ifp; ifp = ifp->if_next) |
if (ifp->if_snd.ifq_maxlen == 0) |
ifp->if_snd.ifq_maxlen = ifqmaxlen; |
if_slowtimo(0); |
} |
|
int if_index = 0; |
struct ifaddr **ifnet_addrs; |
|
|
/* |
* Attach an interface to the |
* list of "active" interfaces. |
*/ |
void |
if_attach(ifp) |
struct ifnet *ifp; |
{ |
unsigned socksize, ifasize; |
int namelen, masklen; |
char workbuf[64]; |
register struct ifnet **p = &ifnet; |
register struct sockaddr_dl *sdl; |
register struct ifaddr *ifa; |
static int if_indexlim = 8; |
|
|
while (*p) |
p = &((*p)->if_next); |
*p = ifp; |
ifp->if_index = ++if_index; |
microtime(&ifp->if_lastchange); |
if (ifnet_addrs == 0 || if_index >= if_indexlim) { |
unsigned n = (if_indexlim <<= 1) * sizeof(ifa); |
struct ifaddr **q = (struct ifaddr **) |
malloc(n, M_IFADDR, M_WAITOK); |
bzero((caddr_t)q, n); |
if (ifnet_addrs) { |
bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2); |
free((caddr_t)ifnet_addrs, M_IFADDR); |
} |
ifnet_addrs = q; |
} |
/* |
* create a Link Level name for this device |
*/ |
namelen = sprintf(workbuf, "%s%d", ifp->if_name, ifp->if_unit); |
#define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) |
masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen; |
socksize = masklen + ifp->if_addrlen; |
#define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) |
socksize = ROUNDUP(socksize); |
if (socksize < sizeof(*sdl)) |
socksize = sizeof(*sdl); |
ifasize = sizeof(*ifa) + 2 * socksize; |
ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK); |
if (ifa) { |
bzero((caddr_t)ifa, ifasize); |
sdl = (struct sockaddr_dl *)(ifa + 1); |
sdl->sdl_len = socksize; |
sdl->sdl_family = AF_LINK; |
bcopy(workbuf, sdl->sdl_data, namelen); |
sdl->sdl_nlen = namelen; |
sdl->sdl_index = ifp->if_index; |
sdl->sdl_type = ifp->if_type; |
ifnet_addrs[if_index - 1] = ifa; |
ifa->ifa_ifp = ifp; |
ifa->ifa_next = ifp->if_addrlist; |
ifa->ifa_rtrequest = link_rtrequest; |
ifp->if_addrlist = ifa; |
ifa->ifa_addr = (struct sockaddr *)sdl; |
|
sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); |
ifa->ifa_netmask = (struct sockaddr *)sdl; |
sdl->sdl_len = masklen; |
while (namelen != 0) |
sdl->sdl_data[--namelen] = 0xff; |
} |
} |
/* |
* Locate an interface based on a complete address. |
*/ |
/*ARGSUSED*/ |
struct ifaddr * |
ifa_ifwithaddr(addr) |
register struct sockaddr *addr; |
{ |
register struct ifnet *ifp; |
register struct ifaddr *ifa; |
|
#define equal(a1, a2) \ |
(bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0) |
for (ifp = ifnet; ifp; ifp = ifp->if_next) |
for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { |
if (ifa->ifa_addr->sa_family != addr->sa_family) |
continue; |
if (equal(addr, ifa->ifa_addr)) |
return (ifa); |
if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr && |
equal(ifa->ifa_broadaddr, addr)) |
return (ifa); |
} |
return ((struct ifaddr *)0); |
} |
/* |
* Locate the point to point interface with a given destination address. |
*/ |
/*ARGSUSED*/ |
struct ifaddr * |
ifa_ifwithdstaddr(addr) |
register struct sockaddr *addr; |
{ |
register struct ifnet *ifp; |
register struct ifaddr *ifa; |
|
for (ifp = ifnet; ifp; ifp = ifp->if_next) |
if (ifp->if_flags & IFF_POINTOPOINT) |
for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { |
if (ifa->ifa_addr->sa_family != addr->sa_family) |
continue; |
if (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)) |
return (ifa); |
} |
return ((struct ifaddr *)0); |
} |
|
/* |
* Find an interface on a specific network. If many, choice |
* is most specific found. |
*/ |
struct ifaddr * |
ifa_ifwithnet(addr) |
struct sockaddr *addr; |
{ |
register struct ifnet *ifp; |
register struct ifaddr *ifa; |
struct ifaddr *ifa_maybe = (struct ifaddr *) 0; |
u_int af = addr->sa_family; |
char *addr_data = addr->sa_data, *cplim; |
|
if (af == AF_LINK) { |
register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr; |
if (sdl->sdl_index && sdl->sdl_index <= if_index) |
return (ifnet_addrs[sdl->sdl_index - 1]); |
} |
for (ifp = ifnet; ifp; ifp = ifp->if_next) { |
for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { |
register char *cp, *cp2, *cp3; |
|
if (ifa->ifa_addr->sa_family != af) |
next: continue; |
if (ifp->if_flags & IFF_POINTOPOINT) { |
if (ifa->ifa_dstaddr != 0 |
&& equal(addr, ifa->ifa_dstaddr)) |
return (ifa); |
} else { |
/* |
* if we have a special address handler, |
* then use it instead of the generic one. |
*/ |
if (ifa->ifa_claim_addr) { |
if ((*ifa->ifa_claim_addr)(ifa, addr)) { |
return (ifa); |
} else { |
continue; |
} |
} |
|
/* |
* Scan all the bits in the ifa's address. |
* If a bit dissagrees with what we are |
* looking for, mask it with the netmask |
* to see if it really matters. |
* (A byte at a time) |
*/ |
if (ifa->ifa_netmask == 0) |
continue; |
cp = addr_data; |
cp2 = ifa->ifa_addr->sa_data; |
cp3 = ifa->ifa_netmask->sa_data; |
cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; |
while (cp3 < cplim) |
if ((*cp++ ^ *cp2++) & *cp3++) |
goto next; |
if (ifa_maybe == 0 || |
rn_refines((caddr_t)ifa->ifa_netmask, |
(caddr_t)ifa_maybe->ifa_netmask)) |
ifa_maybe = ifa; |
} |
} |
} |
return (ifa_maybe); |
} |
|
/* |
* Find an interface address specific to an interface best matching |
* a given address. |
*/ |
struct ifaddr * |
ifaof_ifpforaddr(addr, ifp) |
struct sockaddr *addr; |
register struct ifnet *ifp; |
{ |
register struct ifaddr *ifa; |
register char *cp, *cp2, *cp3; |
register char *cplim; |
struct ifaddr *ifa_maybe = 0; |
u_int af = addr->sa_family; |
|
if (af >= AF_MAX) |
return (0); |
for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { |
if (ifa->ifa_addr->sa_family != af) |
continue; |
if (ifa_maybe == 0) |
ifa_maybe = ifa; |
if (ifa->ifa_netmask == 0) { |
if (equal(addr, ifa->ifa_addr) || |
(ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))) |
return (ifa); |
continue; |
} |
if (ifp->if_flags & IFF_POINTOPOINT) { |
if (equal(addr, ifa->ifa_dstaddr)) |
return (ifa); |
} else { |
cp = addr->sa_data; |
cp2 = ifa->ifa_addr->sa_data; |
cp3 = ifa->ifa_netmask->sa_data; |
cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; |
for (; cp3 < cplim; cp3++) |
if ((*cp++ ^ *cp2++) & *cp3) |
break; |
if (cp3 == cplim) |
return (ifa); |
} |
} |
return (ifa_maybe); |
} |
|
#include <net/route.h> |
|
/* |
* Default action when installing a route with a Link Level gateway. |
* Lookup an appropriate real ifa to point to. |
* This should be moved to /sys/net/link.c eventually. |
*/ |
static void |
link_rtrequest(cmd, rt, sa) |
int cmd; |
register struct rtentry *rt; |
struct sockaddr *sa; |
{ |
register struct ifaddr *ifa; |
struct sockaddr *dst; |
struct ifnet *ifp; |
|
if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || |
((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) |
return; |
ifa = ifaof_ifpforaddr(dst, ifp); |
if (ifa) { |
IFAFREE(rt->rt_ifa); |
rt->rt_ifa = ifa; |
ifa->ifa_refcnt++; |
if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) |
ifa->ifa_rtrequest(cmd, rt, sa); |
} |
} |
|
/* |
* Mark an interface down and notify protocols of |
* the transition. |
* NOTE: must be called at splnet or eqivalent. |
*/ |
void |
if_down(ifp) |
register struct ifnet *ifp; |
{ |
register struct ifaddr *ifa; |
|
ifp->if_flags &= ~IFF_UP; |
microtime(&ifp->if_lastchange); |
for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) |
pfctlinput(PRC_IFDOWN, ifa->ifa_addr); |
if_qflush(&ifp->if_snd); |
rt_ifmsg(ifp); |
} |
|
/* |
* Mark an interface up and notify protocols of |
* the transition. |
* NOTE: must be called at splnet or eqivalent. |
*/ |
void |
if_up(ifp) |
register struct ifnet *ifp; |
{ |
|
ifp->if_flags |= IFF_UP; |
microtime(&ifp->if_lastchange); |
#ifdef notyet |
register struct ifaddr *ifa; |
/* this has no effect on IP, and will kill all iso connections XXX */ |
for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) |
pfctlinput(PRC_IFUP, ifa->ifa_addr); |
#endif |
rt_ifmsg(ifp); |
} |
|
/* |
* Flush an interface queue. |
*/ |
static void |
if_qflush(ifq) |
register struct ifqueue *ifq; |
{ |
register struct mbuf *m, *n; |
|
n = ifq->ifq_head; |
while ((m = n) != 0) { |
n = m->m_act; |
m_freem(m); |
} |
ifq->ifq_head = 0; |
ifq->ifq_tail = 0; |
ifq->ifq_len = 0; |
} |
|
/* |
* Handle interface watchdog timer routines. Called |
* from softclock, we decrement timers (if set) and |
* call the appropriate interface routine on expiration. |
*/ |
static void |
if_slowtimo(arg) |
void *arg; |
{ |
register struct ifnet *ifp; |
int s = splimp(); |
|
for (ifp = ifnet; ifp; ifp = ifp->if_next) { |
if (ifp->if_timer == 0 || --ifp->if_timer) |
continue; |
if (ifp->if_watchdog) |
(*ifp->if_watchdog)(ifp); |
} |
splx(s); |
timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ); |
} |
|
/* |
* Map interface name to |
* interface structure pointer. |
*/ |
struct ifnet * |
ifunit(name) |
register char *name; |
{ |
register char *cp; |
register struct ifnet *ifp; |
int unit; |
unsigned len; |
char *ep, c; |
|
for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) |
if (*cp >= '0' && *cp <= '9') |
break; |
if (*cp == '\0' || cp == name + IFNAMSIZ) |
return ((struct ifnet *)0); |
/* |
* Save first char of unit, and pointer to it, |
* so we can put a null there to avoid matching |
* initial substrings of interface names. |
*/ |
len = cp - name + 1; |
c = *cp; |
ep = cp; |
for (unit = 0; *cp >= '0' && *cp <= '9'; ) |
unit = unit * 10 + *cp++ - '0'; |
if (*cp != '\0') |
return 0; /* no trailing garbage allowed */ |
*ep = 0; |
for (ifp = ifnet; ifp; ifp = ifp->if_next) { |
if (bcmp(ifp->if_name, name, len)) |
continue; |
if (unit == ifp->if_unit) |
break; |
} |
*ep = c; |
return (ifp); |
} |
|
/* |
* Interface ioctls. |
*/ |
int |
ifioctl(so, cmd, data, p) |
struct socket *so; |
int cmd; |
caddr_t data; |
struct proc *p; |
{ |
register struct ifnet *ifp; |
register struct ifreq *ifr; |
int error; |
|
switch (cmd) { |
|
case SIOCGIFCONF: |
case OSIOCGIFCONF: |
return (ifconf(cmd, data)); |
} |
ifr = (struct ifreq *)data; |
ifp = ifunit(ifr->ifr_name); |
if (ifp == 0) |
return (ENXIO); |
switch (cmd) { |
|
case SIOCGIFFLAGS: |
ifr->ifr_flags = ifp->if_flags; |
break; |
|
case SIOCGIFMETRIC: |
ifr->ifr_metric = ifp->if_metric; |
break; |
|
case SIOCGIFMTU: |
ifr->ifr_mtu = ifp->if_mtu; |
break; |
|
case SIOCGIFPHYS: |
ifr->ifr_phys = ifp->if_physical; |
break; |
|
case SIOCSIFFLAGS: |
error = suser(p->p_ucred, &p->p_acflag); |
if (error) |
return (error); |
if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { |
int s = splimp(); |
if_down(ifp); |
splx(s); |
} |
if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) { |
int s = splimp(); |
if_up(ifp); |
splx(s); |
} |
ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | |
(ifr->ifr_flags &~ IFF_CANTCHANGE); |
if (ifp->if_ioctl) |
(void) (*ifp->if_ioctl)(ifp, cmd, data); |
microtime(&ifp->if_lastchange); |
break; |
|
case SIOCSIFMETRIC: |
error = suser(p->p_ucred, &p->p_acflag); |
if (error) |
return (error); |
ifp->if_metric = ifr->ifr_metric; |
microtime(&ifp->if_lastchange); |
break; |
|
case SIOCSIFPHYS: |
error = suser(p->p_ucred, &p->p_acflag); |
if (error) |
return error; |
if (!ifp->if_ioctl) |
return EOPNOTSUPP; |
error = (*ifp->if_ioctl)(ifp, cmd, data); |
if (error == 0) |
microtime(&ifp->if_lastchange); |
return(error); |
|
case SIOCSIFMTU: |
error = suser(p->p_ucred, &p->p_acflag); |
if (error) |
return (error); |
if (ifp->if_ioctl == NULL) |
return (EOPNOTSUPP); |
/* |
* 72 was chosen below because it is the size of a TCP/IP |
* header (40) + the minimum mss (32). |
*/ |
if (ifr->ifr_mtu < 72 || ifr->ifr_mtu > 65535) |
return (EINVAL); |
error = (*ifp->if_ioctl)(ifp, cmd, data); |
if (error == 0) |
microtime(&ifp->if_lastchange); |
return(error); |
|
case SIOCADDMULTI: |
case SIOCDELMULTI: |
error = suser(p->p_ucred, &p->p_acflag); |
if (error) |
return (error); |
if (ifp->if_ioctl == NULL) |
return (EOPNOTSUPP); |
error = (*ifp->if_ioctl)(ifp, cmd, data); |
if (error == 0 ) |
microtime(&ifp->if_lastchange); |
return(error); |
|
case SIOCSIFMEDIA: |
error = suser(p->p_ucred, &p->p_acflag); |
if (error) |
return (error); |
if (ifp->if_ioctl == 0) |
return (EOPNOTSUPP); |
error = (*ifp->if_ioctl)(ifp, cmd, data); |
if (error == 0) |
microtime(&ifp->if_lastchange); |
return error; |
|
case SIOCGIFMEDIA: |
if (ifp->if_ioctl == 0) |
return (EOPNOTSUPP); |
return ((*ifp->if_ioctl)(ifp, cmd, data)); |
|
default: |
if (so->so_proto == 0) |
return (EOPNOTSUPP); |
#ifndef COMPAT_43 |
return ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd, |
data, |
ifp)); |
#else |
{ |
int ocmd = cmd; |
|
switch (cmd) { |
|
case SIOCSIFDSTADDR: |
case SIOCSIFADDR: |
case SIOCSIFBRDADDR: |
case SIOCSIFNETMASK: |
#if BYTE_ORDER != BIG_ENDIAN |
if (ifr->ifr_addr.sa_family == 0 && |
ifr->ifr_addr.sa_len < 16) { |
ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; |
ifr->ifr_addr.sa_len = 16; |
} |
#else |
if (ifr->ifr_addr.sa_len == 0) |
ifr->ifr_addr.sa_len = 16; |
#endif |
break; |
|
case OSIOCGIFADDR: |
cmd = SIOCGIFADDR; |
break; |
|
case OSIOCGIFDSTADDR: |
cmd = SIOCGIFDSTADDR; |
break; |
|
case OSIOCGIFBRDADDR: |
cmd = SIOCGIFBRDADDR; |
break; |
|
case OSIOCGIFNETMASK: |
cmd = SIOCGIFNETMASK; |
} |
error = ((*so->so_proto->pr_usrreqs->pru_control)(so, |
cmd, |
data, |
ifp)); |
switch (ocmd) { |
|
case OSIOCGIFADDR: |
case OSIOCGIFDSTADDR: |
case OSIOCGIFBRDADDR: |
case OSIOCGIFNETMASK: |
*(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; |
} |
return (error); |
|
} |
#endif |
|
/* |
* RTEMS additions for setting/getting `tap' function |
*/ |
case SIOCSIFTAP: |
ifp->if_tap = ifr->ifr_tap; |
return 0; |
|
case SIOCGIFTAP: |
ifr->ifr_tap = ifp->if_tap; |
return 0; |
} |
return (0); |
} |
|
/* |
* Set/clear promiscuous mode on interface ifp based on the truth value |
* of pswitch. The calls are reference counted so that only the first |
* "on" request actually has an effect, as does the final "off" request. |
* Results are undefined if the "off" and "on" requests are not matched. |
*/ |
int |
ifpromisc(ifp, pswitch) |
struct ifnet *ifp; |
int pswitch; |
{ |
struct ifreq ifr; |
|
if (pswitch) { |
/* |
* If the device is not configured up, we cannot put it in |
* promiscuous mode. |
*/ |
if ((ifp->if_flags & IFF_UP) == 0) |
return (ENETDOWN); |
if (ifp->if_pcount++ != 0) |
return (0); |
ifp->if_flags |= IFF_PROMISC; |
log(LOG_INFO, "%s%d: promiscuous mode enabled\n", |
ifp->if_name, ifp->if_unit); |
} else { |
if (--ifp->if_pcount > 0) |
return (0); |
ifp->if_flags &= ~IFF_PROMISC; |
} |
ifr.ifr_flags = ifp->if_flags; |
return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr)); |
} |
|
/* |
* Return interface configuration |
* of system. List may be used |
* in later ioctl's (above) to get |
* other information. |
*/ |
/*ARGSUSED*/ |
static int |
ifconf(cmd, data) |
int cmd; |
caddr_t data; |
{ |
register struct ifconf *ifc = (struct ifconf *)data; |
register struct ifnet *ifp = ifnet; |
register struct ifaddr *ifa; |
struct ifreq ifr, *ifrp; |
int space = ifc->ifc_len, error = 0; |
|
ifrp = ifc->ifc_req; |
for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { |
char workbuf[64]; |
int ifnlen; |
|
ifnlen = sprintf(workbuf, "%s%d", ifp->if_name, ifp->if_unit); |
if(ifnlen + 1 > sizeof ifr.ifr_name) { |
error = ENAMETOOLONG; |
} else { |
strcpy(ifr.ifr_name, workbuf); |
} |
|
if ((ifa = ifp->if_addrlist) == 0) { |
bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); |
error = copyout((caddr_t)&ifr, (caddr_t)ifrp, |
sizeof (ifr)); |
if (error) |
break; |
space -= sizeof (ifr), ifrp++; |
} else |
for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { |
register struct sockaddr *sa = ifa->ifa_addr; |
#ifdef COMPAT_43 |
if (cmd == OSIOCGIFCONF) { |
struct osockaddr *osa = |
(struct osockaddr *)&ifr.ifr_addr; |
ifr.ifr_addr = *sa; |
osa->sa_family = sa->sa_family; |
error = copyout((caddr_t)&ifr, (caddr_t)ifrp, |
sizeof (ifr)); |
ifrp++; |
} else |
#endif |
if (sa->sa_len <= sizeof(*sa)) { |
ifr.ifr_addr = *sa; |
error = copyout((caddr_t)&ifr, (caddr_t)ifrp, |
sizeof (ifr)); |
ifrp++; |
} else { |
space -= sa->sa_len - sizeof(*sa); |
if (space < sizeof (ifr)) |
break; |
error = copyout((caddr_t)&ifr, (caddr_t)ifrp, |
sizeof (ifr.ifr_name)); |
if (error == 0) |
error = copyout((caddr_t)sa, |
(caddr_t)&ifrp->ifr_addr, sa->sa_len); |
ifrp = (struct ifreq *) |
(sa->sa_len + (caddr_t)&ifrp->ifr_addr); |
} |
if (error) |
break; |
space -= sizeof (ifr); |
} |
} |
ifc->ifc_len -= space; |
return (error); |
} |
|
SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers"); |
SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management"); |
/ppp-comp.h
0,0 → 1,165
/* |
* ppp-comp.h - Definitions for doing PPP packet compression. |
* |
* Copyright (c) 1994 The Australian National University. |
* All rights reserved. |
* |
* Permission to use, copy, modify, and distribute this software and its |
* documentation is hereby granted, provided that the above copyright |
* notice appears in all copies. This software is provided without any |
* warranty, express or implied. The Australian National University |
* makes no representations about the suitability of this software for |
* any purpose. |
* |
* IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY |
* PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF |
* THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY |
* OF SUCH DAMAGE. |
* |
* THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, |
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY |
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
* ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO |
* OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, |
* OR MODIFICATIONS. |
* |
* $Id: ppp-comp.h,v 1.2 2001-09-27 12:01:54 chris Exp $ |
*/ |
|
#ifndef _NET_PPP_COMP_H |
#define _NET_PPP_COMP_H |
|
/* |
* The following symbols control whether we include code for |
* various compression methods. |
*/ |
#ifndef DO_BSD_COMPRESS |
#define DO_BSD_COMPRESS 1 /* by default, include BSD-Compress */ |
#endif |
#ifndef DO_DEFLATE |
#define DO_DEFLATE 1 /* by default, include Deflate */ |
#endif |
#define DO_PREDICTOR_1 0 |
#define DO_PREDICTOR_2 0 |
|
/* |
* Structure giving methods for compression/decompression. |
*/ |
#ifdef PACKETPTR |
struct compressor { |
int compress_proto; /* CCP compression protocol number */ |
|
/* Allocate space for a compressor (transmit side) */ |
void *(*comp_alloc) __P((u_char *options, int opt_len)); |
/* Free space used by a compressor */ |
void (*comp_free) __P((void *state)); |
/* Initialize a compressor */ |
int (*comp_init) __P((void *state, u_char *options, int opt_len, |
int unit, int hdrlen, int debug)); |
/* Reset a compressor */ |
void (*comp_reset) __P((void *state)); |
/* Compress a packet */ |
int (*compress) __P((void *state, PACKETPTR *mret, |
PACKETPTR mp, int orig_len, int max_len)); |
/* Return compression statistics */ |
void (*comp_stat) __P((void *state, struct compstat *stats)); |
|
/* Allocate space for a decompressor (receive side) */ |
void *(*decomp_alloc) __P((u_char *options, int opt_len)); |
/* Free space used by a decompressor */ |
void (*decomp_free) __P((void *state)); |
/* Initialize a decompressor */ |
int (*decomp_init) __P((void *state, u_char *options, int opt_len, |
int unit, int hdrlen, int mru, int debug)); |
/* Reset a decompressor */ |
void (*decomp_reset) __P((void *state)); |
/* Decompress a packet. */ |
int (*decompress) __P((void *state, PACKETPTR mp, |
PACKETPTR *dmpp)); |
/* Update state for an incompressible packet received */ |
void (*incomp) __P((void *state, PACKETPTR mp)); |
/* Return decompression statistics */ |
void (*decomp_stat) __P((void *state, struct compstat *stats)); |
}; |
#endif /* PACKETPTR */ |
|
/* |
* Return values for decompress routine. |
* We need to make these distinctions so that we can disable certain |
* useful functionality, namely sending a CCP reset-request as a result |
* of an error detected after decompression. This is to avoid infringing |
* a patent held by Motorola. |
* Don't you just lurve software patents. |
*/ |
#define DECOMP_OK 0 /* everything went OK */ |
#define DECOMP_ERROR 1 /* error detected before decomp. */ |
#define DECOMP_FATALERROR 2 /* error detected after decomp. */ |
|
/* |
* CCP codes. |
*/ |
#define CCP_CONFREQ 1 |
#define CCP_CONFACK 2 |
#define CCP_TERMREQ 5 |
#define CCP_TERMACK 6 |
#define CCP_RESETREQ 14 |
#define CCP_RESETACK 15 |
|
/* |
* Max # bytes for a CCP option |
*/ |
#define CCP_MAX_OPTION_LENGTH 32 |
|
/* |
* Parts of a CCP packet. |
*/ |
#define CCP_CODE(dp) ((dp)[0]) |
#define CCP_ID(dp) ((dp)[1]) |
#define CCP_LENGTH(dp) (((dp)[2] << 8) + (dp)[3]) |
#define CCP_HDRLEN 4 |
|
#define CCP_OPT_CODE(dp) ((dp)[0]) |
#define CCP_OPT_LENGTH(dp) ((dp)[1]) |
#define CCP_OPT_MINLEN 2 |
|
/* |
* Definitions for BSD-Compress. |
*/ |
#define CI_BSD_COMPRESS 21 /* config. option for BSD-Compress */ |
#define CILEN_BSD_COMPRESS 3 /* length of config. option */ |
|
/* Macros for handling the 3rd byte of the BSD-Compress config option. */ |
#define BSD_NBITS(x) ((x) & 0x1F) /* number of bits requested */ |
#define BSD_VERSION(x) ((x) >> 5) /* version of option format */ |
#define BSD_CURRENT_VERSION 1 /* current version number */ |
#define BSD_MAKE_OPT(v, n) (((v) << 5) | (n)) |
|
#define BSD_MIN_BITS 9 /* smallest code size supported */ |
#define BSD_MAX_BITS 15 /* largest code size supported */ |
|
/* |
* Definitions for Deflate. |
*/ |
#define CI_DEFLATE 26 /* config option for Deflate */ |
#define CI_DEFLATE_DRAFT 24 /* value used in original draft RFC */ |
#define CILEN_DEFLATE 4 /* length of its config option */ |
|
#define DEFLATE_MIN_SIZE 8 |
#define DEFLATE_MAX_SIZE 15 |
#define DEFLATE_METHOD_VAL 8 |
#define DEFLATE_SIZE(x) (((x) >> 4) + DEFLATE_MIN_SIZE) |
#define DEFLATE_METHOD(x) ((x) & 0x0F) |
#define DEFLATE_MAKE_OPT(w) ((((w) - DEFLATE_MIN_SIZE) << 4) \ |
+ DEFLATE_METHOD_VAL) |
#define DEFLATE_CHK_SEQUENCE 0 |
|
/* |
* Definitions for other, as yet unsupported, compression methods. |
*/ |
#define CI_PREDICTOR_1 1 /* config option for Predictor-1 */ |
#define CILEN_PREDICTOR_1 2 /* length of its config option */ |
#define CI_PREDICTOR_2 2 /* config option for Predictor-2 */ |
#define CILEN_PREDICTOR_2 2 /* length of its config option */ |
|
#endif /* _NET_PPP_COMP_H */ |
/raw_cb.h
0,0 → 1,75
/* |
* Copyright (c) 1980, 1986, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)raw_cb.h 8.1 (Berkeley) 6/10/93 |
* $Id: raw_cb.h,v 1.2 2001-09-27 12:01:54 chris Exp $ |
*/ |
|
#ifndef _NET_RAW_CB_H_ |
#define _NET_RAW_CB_H_ |
|
/* |
* Raw protocol interface control block. Used |
* to tie a socket to the generic raw interface. |
*/ |
struct rawcb { |
struct rawcb *rcb_next; /* doubly linked list */ |
struct rawcb *rcb_prev; |
struct socket *rcb_socket; /* back pointer to socket */ |
struct sockaddr *rcb_faddr; /* destination address */ |
struct sockaddr *rcb_laddr; /* socket's address */ |
struct sockproto rcb_proto; /* protocol family, protocol */ |
}; |
|
#define sotorawcb(so) ((struct rawcb *)(so)->so_pcb) |
|
/* |
* Nominal space allocated to a raw socket. |
*/ |
#define RAWSNDQ 8192 |
#define RAWRCVQ 8192 |
|
#ifdef KERNEL |
extern struct rawcb rawcb; /* head of list */ |
|
int raw_attach __P((struct socket *, int)); |
void raw_ctlinput __P((int, struct sockaddr *, void *)); |
void raw_detach __P((struct rawcb *)); |
void raw_disconnect __P((struct rawcb *)); |
void raw_init __P((void)); |
void raw_input __P((struct mbuf *, |
struct sockproto *, struct sockaddr *, struct sockaddr *)); |
int raw_usrreq __P((struct socket *, |
int, struct mbuf *, struct mbuf *, struct mbuf *)); |
#endif |
|
#endif |
/route.h
0,0 → 1,286
/* |
* Copyright (c) 1980, 1986, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)route.h 8.3 (Berkeley) 4/19/94 |
* $Id: route.h,v 1.2 2001-09-27 12:01:54 chris Exp $ |
*/ |
|
#ifndef _NET_ROUTE_H_ |
#define _NET_ROUTE_H_ |
|
/* |
* Kernel resident routing tables. |
* |
* The routing tables are initialized when interface addresses |
* are set by making entries for all directly connected interfaces. |
*/ |
|
/* |
* A route consists of a destination address and a reference |
* to a routing entry. These are often held by protocols |
* in their control blocks, e.g. inpcb. |
*/ |
struct route { |
struct rtentry *ro_rt; |
struct sockaddr ro_dst; |
}; |
|
/* |
* These numbers are used by reliable protocols for determining |
* retransmission behavior and are included in the routing structure. |
*/ |
struct rt_metrics { |
u_long rmx_locks; /* Kernel must leave these values alone */ |
u_long rmx_mtu; /* MTU for this path */ |
u_long rmx_hopcount; /* max hops expected */ |
u_long rmx_expire; /* lifetime for route, e.g. redirect */ |
u_long rmx_recvpipe; /* inbound delay-bandwidth product */ |
u_long rmx_sendpipe; /* outbound delay-bandwidth product */ |
u_long rmx_ssthresh; /* outbound gateway buffer limit */ |
u_long rmx_rtt; /* estimated round trip time */ |
u_long rmx_rttvar; /* estimated rtt variance */ |
u_long rmx_pksent; /* packets sent using this route */ |
u_long rmx_filler[4]; /* will be used for T/TCP later */ |
}; |
|
/* |
* rmx_rtt and rmx_rttvar are stored as microseconds; |
* RTTTOPRHZ(rtt) converts to a value suitable for use |
* by a protocol slowtimo counter. |
*/ |
#define RTM_RTTUNIT 1000000 /* units for rtt, rttvar, as units per sec */ |
#define RTTTOPRHZ(r) ((r) / (RTM_RTTUNIT / PR_SLOWHZ)) |
|
/* |
* XXX kernel function pointer `rt_output' is visible to applications. |
*/ |
struct mbuf; |
|
/* |
* We distinguish between routes to hosts and routes to networks, |
* preferring the former if available. For each route we infer |
* the interface to use from the gateway address supplied when |
* the route was entered. Routes that forward packets through |
* gateways are marked so that the output routines know to address the |
* gateway rather than the ultimate destination. |
*/ |
#ifndef RNF_NORMAL |
#include <net/radix.h> |
#endif |
struct rtentry { |
struct radix_node rt_nodes[2]; /* tree glue, and other values */ |
#define rt_key(r) ((struct sockaddr *)((r)->rt_nodes->rn_key)) |
#define rt_mask(r) ((struct sockaddr *)((r)->rt_nodes->rn_mask)) |
struct sockaddr *rt_gateway; /* value */ |
short rt_filler; /* was short flags field */ |
short rt_refcnt; /* # held references */ |
u_long rt_flags; /* up/down?, host/net */ |
struct ifnet *rt_ifp; /* the answer: interface to use */ |
struct ifaddr *rt_ifa; /* the answer: interface to use */ |
struct sockaddr *rt_genmask; /* for generation of cloned routes */ |
caddr_t rt_llinfo; /* pointer to link level info cache */ |
struct rt_metrics rt_rmx; /* metrics used by rx'ing protocols */ |
struct rtentry *rt_gwroute; /* implied entry for gatewayed routes */ |
int (*rt_output) __P((struct ifnet *, struct mbuf *, |
struct sockaddr *, struct rtentry *)); |
/* output routine for this (rt,if) */ |
struct rtentry *rt_parent; /* cloning parent of this route */ |
void *rt_filler2; /* more filler */ |
}; |
|
/* |
* Following structure necessary for 4.3 compatibility; |
* We should eventually move it to a compat file. |
*/ |
struct ortentry { |
u_long rt_hash; /* to speed lookups */ |
struct sockaddr rt_dst; /* key */ |
struct sockaddr rt_gateway; /* value */ |
short rt_flags; /* up/down?, host/net */ |
short rt_refcnt; /* # held references */ |
u_long rt_use; /* raw # packets forwarded */ |
struct ifnet *rt_ifp; /* the answer: interface to use */ |
}; |
|
#define rt_use rt_rmx.rmx_pksent |
|
#define RTF_UP 0x1 /* route usable */ |
#define RTF_GATEWAY 0x2 /* destination is a gateway */ |
#define RTF_HOST 0x4 /* host entry (net otherwise) */ |
#define RTF_REJECT 0x8 /* host or net unreachable */ |
#define RTF_DYNAMIC 0x10 /* created dynamically (by redirect) */ |
#define RTF_MODIFIED 0x20 /* modified dynamically (by redirect) */ |
#define RTF_DONE 0x40 /* message confirmed */ |
/* 0x80 unused */ |
#define RTF_CLONING 0x100 /* generate new routes on use */ |
#define RTF_XRESOLVE 0x200 /* external daemon resolves name */ |
#define RTF_LLINFO 0x400 /* generated by link layer (e.g. ARP) */ |
#define RTF_STATIC 0x800 /* manually added */ |
#define RTF_BLACKHOLE 0x1000 /* just discard pkts (during updates) */ |
#define RTF_PROTO2 0x4000 /* protocol specific routing flag */ |
#define RTF_PROTO1 0x8000 /* protocol specific routing flag */ |
|
#define RTF_PRCLONING 0x10000 /* protocol requires cloning */ |
#define RTF_WASCLONED 0x20000 /* route generated through cloning */ |
#define RTF_PROTO3 0x40000 /* protocol specific routing flag */ |
/* 0x80000 unused */ |
#define RTF_PINNED 0x100000 /* future use */ |
#define RTF_LOCAL 0x200000 /* route represents a local address */ |
#define RTF_BROADCAST 0x400000 /* route represents a bcast address */ |
#define RTF_MULTICAST 0x800000 /* route represents a mcast address */ |
/* 0x1000000 and up unassigned */ |
|
/* |
* Routing statistics. |
*/ |
struct rtstat { |
short rts_badredirect; /* bogus redirect calls */ |
short rts_dynamic; /* routes created by redirects */ |
short rts_newgateway; /* routes modified by redirects */ |
short rts_unreach; /* lookups which failed */ |
short rts_wildcard; /* lookups satisfied by a wildcard */ |
}; |
/* |
* Structures for routing messages. |
*/ |
struct rt_msghdr { |
u_short rtm_msglen; /* to skip over non-understood messages */ |
u_char rtm_version; /* future binary compatibility */ |
u_char rtm_type; /* message type */ |
u_short rtm_index; /* index for associated ifp */ |
int rtm_flags; /* flags, incl. kern & message, e.g. DONE */ |
int rtm_addrs; /* bitmask identifying sockaddrs in msg */ |
pid_t rtm_pid; /* identify sender */ |
int rtm_seq; /* for sender to identify action */ |
int rtm_errno; /* why failed */ |
int rtm_use; /* from rtentry */ |
u_long rtm_inits; /* which metrics we are initializing */ |
struct rt_metrics rtm_rmx; /* metrics themselves */ |
}; |
|
#define RTM_VERSION 5 /* Up the ante and ignore older versions */ |
|
#define RTM_ADD 0x1 /* Add Route */ |
#define RTM_DELETE 0x2 /* Delete Route */ |
#define RTM_CHANGE 0x3 /* Change Metrics or flags */ |
#define RTM_GET 0x4 /* Report Metrics */ |
#define RTM_LOSING 0x5 /* Kernel Suspects Partitioning */ |
#define RTM_REDIRECT 0x6 /* Told to use different route */ |
#define RTM_MISS 0x7 /* Lookup failed on this address */ |
#define RTM_LOCK 0x8 /* fix specified metrics */ |
#define RTM_OLDADD 0x9 /* caused by SIOCADDRT */ |
#define RTM_OLDDEL 0xa /* caused by SIOCDELRT */ |
#define RTM_RESOLVE 0xb /* req to resolve dst to LL addr */ |
#define RTM_NEWADDR 0xc /* address being added to iface */ |
#define RTM_DELADDR 0xd /* address being removed from iface */ |
#define RTM_IFINFO 0xe /* iface going up/down etc. */ |
|
#define RTV_MTU 0x1 /* init or lock _mtu */ |
#define RTV_HOPCOUNT 0x2 /* init or lock _hopcount */ |
#define RTV_EXPIRE 0x4 /* init or lock _hopcount */ |
#define RTV_RPIPE 0x8 /* init or lock _recvpipe */ |
#define RTV_SPIPE 0x10 /* init or lock _sendpipe */ |
#define RTV_SSTHRESH 0x20 /* init or lock _ssthresh */ |
#define RTV_RTT 0x40 /* init or lock _rtt */ |
#define RTV_RTTVAR 0x80 /* init or lock _rttvar */ |
|
/* |
* Bitmask values for rtm_addr. |
*/ |
#define RTA_DST 0x1 /* destination sockaddr present */ |
#define RTA_GATEWAY 0x2 /* gateway sockaddr present */ |
#define RTA_NETMASK 0x4 /* netmask sockaddr present */ |
#define RTA_GENMASK 0x8 /* cloning mask sockaddr present */ |
#define RTA_IFP 0x10 /* interface name sockaddr present */ |
#define RTA_IFA 0x20 /* interface addr sockaddr present */ |
#define RTA_AUTHOR 0x40 /* sockaddr for author of redirect */ |
#define RTA_BRD 0x80 /* for NEWADDR, broadcast or p-p dest addr */ |
|
/* |
* Index offsets for sockaddr array for alternate internal encoding. |
*/ |
#define RTAX_DST 0 /* destination sockaddr present */ |
#define RTAX_GATEWAY 1 /* gateway sockaddr present */ |
#define RTAX_NETMASK 2 /* netmask sockaddr present */ |
#define RTAX_GENMASK 3 /* cloning mask sockaddr present */ |
#define RTAX_IFP 4 /* interface name sockaddr present */ |
#define RTAX_IFA 5 /* interface addr sockaddr present */ |
#define RTAX_AUTHOR 6 /* sockaddr for author of redirect */ |
#define RTAX_BRD 7 /* for NEWADDR, broadcast or p-p dest addr */ |
#define RTAX_MAX 8 /* size of array to allocate */ |
|
struct rt_addrinfo { |
int rti_addrs; |
struct sockaddr *rti_info[RTAX_MAX]; |
}; |
|
struct route_cb { |
int ip_count; |
int ipx_count; |
int ns_count; |
int iso_count; |
int any_count; |
}; |
|
#ifdef KERNEL |
#define RTFREE(rt) \ |
do { \ |
if ((rt)->rt_refcnt <= 1) \ |
rtfree(rt); \ |
else \ |
(rt)->rt_refcnt--; \ |
} while (0) |
|
extern struct route_cb route_cb; |
extern struct rtstat rtstat; |
extern struct radix_node_head *rt_tables[AF_MAX+1]; |
|
void route_init __P((void)); |
void rt_ifmsg __P((struct ifnet *)); |
void rt_missmsg __P((int, struct rt_addrinfo *, int, int)); |
void rt_newaddrmsg __P((int, struct ifaddr *, int, struct rtentry *)); |
int rt_setgate __P((struct rtentry *, |
struct sockaddr *, struct sockaddr *)); |
void rtalloc __P((struct route *)); |
void rtalloc_ign __P((struct route *, unsigned long)); |
struct rtentry * |
rtalloc1 __P((struct sockaddr *, int, unsigned long)); |
void rtfree __P((struct rtentry *)); |
int rtinit __P((struct ifaddr *, int, int)); |
int rtioctl __P((int, caddr_t, struct proc *)); |
void rtredirect __P((struct sockaddr *, struct sockaddr *, |
struct sockaddr *, int, struct sockaddr *, struct rtentry **)); |
int rtrequest __P((int, struct sockaddr *, |
struct sockaddr *, struct sockaddr *, int, struct rtentry **)); |
#endif |
|
#endif |
/if.h
0,0 → 1,474
/* |
* Copyright (c) 1982, 1986, 1989, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)if.h 8.1 (Berkeley) 6/10/93 |
* $Id: if.h,v 1.2 2001-09-27 12:01:54 chris Exp $ |
*/ |
|
#ifndef _NET_IF_H_ |
#define _NET_IF_H_ |
|
/* |
* Structures defining a network interface, providing a packet |
* transport mechanism (ala level 0 of the PUP protocols). |
* |
* Each interface accepts output datagrams of a specified maximum |
* length, and provides higher level routines with input datagrams |
* received from its medium. |
* |
* Output occurs when the routine if_output is called, with three parameters: |
* (*ifp->if_output)(ifp, m, dst, rt) |
* Here m is the mbuf chain to be sent and dst is the destination address. |
* The output routine encapsulates the supplied datagram if necessary, |
* and then transmits it on its medium. |
* |
* On input, each interface unwraps the data received by it, and either |
* places it on the input queue of a internetwork datagram routine |
* and posts the associated software interrupt, or passes the datagram to a raw |
* packet input routine. |
* |
* Routines exist for locating interfaces by their addresses |
* or for locating a interface on a certain network, as well as more general |
* routing and gateway routines maintaining information used to locate |
* interfaces. These routines live in the files if.c and route.c |
*/ |
|
#ifndef _TIME_ /* XXX fast fix for SNMP, going away soon */ |
#include <sys/time.h> |
#endif |
|
#ifdef __STDC__ |
/* |
* Forward structure declarations for function prototypes [sic]. |
*/ |
struct mbuf; |
struct proc; |
struct rtentry; |
struct socket; |
struct ether_header; |
#endif |
|
/* |
* Structure describing information about an interface |
* which may be of interest to management entities. |
*/ |
struct if_data { |
/* generic interface information */ |
u_char ifi_type; /* ethernet, tokenring, etc */ |
u_char ifi_physical; /* e.g., AUI, Thinnet, 10base-T, etc */ |
u_char ifi_addrlen; /* media address length */ |
u_char ifi_hdrlen; /* media header length */ |
u_char ifi_recvquota; /* polling quota for receive intrs */ |
u_char ifi_xmitquota; /* polling quota for xmit intrs */ |
u_long ifi_mtu; /* maximum transmission unit */ |
u_long ifi_metric; /* routing metric (external only) */ |
u_long ifi_baudrate; /* linespeed */ |
/* volatile statistics */ |
u_long ifi_ipackets; /* packets received on interface */ |
u_long ifi_ierrors; /* input errors on interface */ |
u_long ifi_opackets; /* packets sent on interface */ |
u_long ifi_oerrors; /* output errors on interface */ |
u_long ifi_collisions; /* collisions on csma interfaces */ |
u_long ifi_ibytes; /* total number of octets received */ |
u_long ifi_obytes; /* total number of octets sent */ |
u_long ifi_imcasts; /* packets received via multicast */ |
u_long ifi_omcasts; /* packets sent via multicast */ |
u_long ifi_iqdrops; /* dropped on input, this interface */ |
u_long ifi_noproto; /* destined for unsupported protocol */ |
u_long ifi_recvtiming; /* usec spent receiving when timing */ |
u_long ifi_xmittiming; /* usec spent xmitting when timing */ |
struct timeval ifi_lastchange; /* time of last administrative change */ |
}; |
|
/* |
* Structure defining a queue for a network interface. |
*/ |
struct ifqueue { |
struct mbuf *ifq_head; |
struct mbuf *ifq_tail; |
int ifq_len; |
int ifq_maxlen; |
int ifq_drops; |
}; |
|
/* |
* Structure defining a network interface. |
* |
* (Would like to call this struct ``if'', but C isn't PL/1.) |
*/ |
struct ifnet { |
void *if_softc; /* pointer to driver state */ |
char *if_name; /* name, e.g. ``en'' or ``lo'' */ |
struct ifnet *if_next; /* all struct ifnets are chained */ |
struct ifaddr *if_addrlist; /* linked list of addresses per if */ |
int if_pcount; /* number of promiscuous listeners */ |
struct bpf_if *if_bpf; /* packet filter structure */ |
u_short if_index; /* numeric abbreviation for this if */ |
short if_unit; /* sub-unit for lower level driver */ |
short if_timer; /* time 'til if_watchdog called */ |
short if_flags; /* up/down, broadcast, etc. */ |
int if_ipending; /* interrupts pending */ |
void *if_linkmib; /* link-type-specific MIB data */ |
size_t if_linkmiblen; /* length of above data */ |
struct if_data if_data; |
/* procedure handles */ |
int (*if_output) /* output routine (enqueue) */ |
__P((struct ifnet *, struct mbuf *, struct sockaddr *, |
struct rtentry *)); |
void (*if_start) /* initiate output routine */ |
__P((struct ifnet *)); |
int (*if_done) /* output complete routine */ |
__P((struct ifnet *)); /* (XXX not used; fake prototype) */ |
int (*if_ioctl) /* ioctl routine */ |
__P((struct ifnet *, int, caddr_t)); |
void (*if_watchdog) /* timer routine */ |
__P((struct ifnet *)); |
int (*if_poll_recv) /* polled receive routine */ |
__P((struct ifnet *, int *)); |
int (*if_poll_xmit) /* polled transmit routine */ |
__P((struct ifnet *, int *)); |
void (*if_poll_intren) /* polled interrupt reenable routine */ |
__P((struct ifnet *)); |
void (*if_poll_slowinput) /* input routine for slow devices */ |
__P((struct ifnet *, struct mbuf *)); |
void (*if_init) /* Init routine */ |
__P((void *)); |
int (*if_tap) /* Packet filter routine */ |
(struct ifnet *, struct ether_header *, struct mbuf *); |
struct ifqueue if_snd; /* output queue */ |
struct ifqueue *if_poll_slowq; /* input queue for slow devices */ |
}; |
typedef void if_init_f_t __P((void *)); |
|
#define if_mtu if_data.ifi_mtu |
#define if_type if_data.ifi_type |
#define if_physical if_data.ifi_physical |
#define if_addrlen if_data.ifi_addrlen |
#define if_hdrlen if_data.ifi_hdrlen |
#define if_metric if_data.ifi_metric |
#define if_baudrate if_data.ifi_baudrate |
#define if_ipackets if_data.ifi_ipackets |
#define if_ierrors if_data.ifi_ierrors |
#define if_opackets if_data.ifi_opackets |
#define if_oerrors if_data.ifi_oerrors |
#define if_collisions if_data.ifi_collisions |
#define if_ibytes if_data.ifi_ibytes |
#define if_obytes if_data.ifi_obytes |
#define if_imcasts if_data.ifi_imcasts |
#define if_omcasts if_data.ifi_omcasts |
#define if_iqdrops if_data.ifi_iqdrops |
#define if_noproto if_data.ifi_noproto |
#define if_lastchange if_data.ifi_lastchange |
#define if_recvquota if_data.ifi_recvquota |
#define if_xmitquota if_data.ifi_xmitquota |
#define if_rawoutput(if, m, sa) if_output(if, m, sa, (struct rtentry *)0) |
|
#define IFF_UP 0x1 /* interface is up */ |
#define IFF_BROADCAST 0x2 /* broadcast address valid */ |
#define IFF_DEBUG 0x4 /* turn on debugging */ |
#define IFF_LOOPBACK 0x8 /* is a loopback net */ |
#define IFF_POINTOPOINT 0x10 /* interface is point-to-point link */ |
/*#define IFF_NOTRAILERS 0x20 * obsolete: avoid use of trailers */ |
#define IFF_RUNNING 0x40 /* resources allocated */ |
#define IFF_NOARP 0x80 /* no address resolution protocol */ |
#define IFF_PROMISC 0x100 /* receive all packets */ |
#define IFF_ALLMULTI 0x200 /* receive all multicast packets */ |
#define IFF_OACTIVE 0x400 /* transmission in progress */ |
#define IFF_SIMPLEX 0x800 /* can't hear own transmissions */ |
#define IFF_LINK0 0x1000 /* per link layer defined bit */ |
#define IFF_LINK1 0x2000 /* per link layer defined bit */ |
#define IFF_LINK2 0x4000 /* per link layer defined bit */ |
#define IFF_ALTPHYS IFF_LINK2 /* use alternate physical connection */ |
#define IFF_MULTICAST 0x8000 /* supports multicast */ |
|
/* flags set internally only: */ |
#define IFF_CANTCHANGE \ |
(IFF_BROADCAST|IFF_POINTOPOINT|IFF_RUNNING|IFF_OACTIVE|\ |
IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI) |
|
|
/* |
* These really don't belong here, but there's no other obviously appropriate |
* location. |
*/ |
#define IFP_AUI 0 |
#define IFP_10BASE2 1 |
#define IFP_10BASET 2 |
/* etc. */ |
|
/* |
* Bit values in if_ipending |
*/ |
#define IFI_RECV 1 /* I want to receive */ |
#define IFI_XMIT 2 /* I want to transmit */ |
|
/* |
* Output queues (ifp->if_snd) and slow device input queues (*ifp->if_slowq) |
* are queues of messages stored on ifqueue structures |
* (defined above). Entries are added to and deleted from these structures |
* by these macros, which should be called with ipl raised to splimp(). |
*/ |
#define IF_QFULL(ifq) ((ifq)->ifq_len >= (ifq)->ifq_maxlen) |
#define IF_DROP(ifq) ((ifq)->ifq_drops++) |
#define IF_ENQUEUE(ifq, m) { \ |
/* printf(" IF_ENQUEUE: %p %p\n", ifq, m ); */ \ |
(m)->m_nextpkt = 0; \ |
if ((ifq)->ifq_tail == 0) \ |
(ifq)->ifq_head = m; \ |
else \ |
(ifq)->ifq_tail->m_nextpkt = m; \ |
(ifq)->ifq_tail = m; \ |
(ifq)->ifq_len++; \ |
} |
#define IF_PREPEND(ifq, m) { \ |
/* printf(" IF_PREPEND: %p %p\n", ifq, m ); */ \ |
(m)->m_nextpkt = (ifq)->ifq_head; \ |
if ((ifq)->ifq_tail == 0) \ |
(ifq)->ifq_tail = (m); \ |
(ifq)->ifq_head = (m); \ |
(ifq)->ifq_len++; \ |
} |
#define IF_DEQUEUE(ifq, m) { \ |
(m) = (ifq)->ifq_head; \ |
if (m) { \ |
/* printf(" IF_DEQUEUE: %p %p\n", ifq, m ); */ \ |
if (((ifq)->ifq_head = (m)->m_nextpkt) == 0) \ |
(ifq)->ifq_tail = 0; \ |
(m)->m_nextpkt = 0; \ |
(ifq)->ifq_len--; \ |
} \ |
} |
|
#ifdef KERNEL |
#define IF_ENQ_DROP(ifq, m) if_enq_drop(ifq, m) |
|
#if defined(__GNUC__) && defined(MT_HEADER) |
static inline int |
if_queue_drop(struct ifqueue *ifq, struct mbuf *m) |
{ |
IF_DROP(ifq); |
return 0; |
} |
|
static inline int |
if_enq_drop(struct ifqueue *ifq, struct mbuf *m) |
{ |
if (IF_QFULL(ifq) && |
!if_queue_drop(ifq, m)) |
return 0; |
IF_ENQUEUE(ifq, m); |
return 1; |
} |
#else |
|
#ifdef MT_HEADER |
int if_enq_drop __P((struct ifqueue *, struct mbuf *)); |
#endif |
|
#endif |
#endif /* KERNEL */ |
|
#define IFQ_MAXLEN 50 |
#define IFNET_SLOWHZ 1 /* granularity is 1 second */ |
|
/* |
* The ifaddr structure contains information about one address |
* of an interface. They are maintained by the different address families, |
* are allocated and attached when an address is set, and are linked |
* together so all addresses for an interface can be located. |
*/ |
struct ifaddr { |
struct sockaddr *ifa_addr; /* address of interface */ |
struct sockaddr *ifa_dstaddr; /* other end of p-to-p link */ |
#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */ |
struct sockaddr *ifa_netmask; /* used to determine subnet */ |
struct ifnet *ifa_ifp; /* back-pointer to interface */ |
struct ifaddr *ifa_next; /* next address for interface */ |
void (*ifa_rtrequest) /* check or clean routes (+ or -)'d */ |
__P((int, struct rtentry *, struct sockaddr *)); |
u_short ifa_flags; /* mostly rt_flags for cloning */ |
short ifa_refcnt; /* references to this structure */ |
int ifa_metric; /* cost of going out this interface */ |
#ifdef notdef |
struct rtentry *ifa_rt; /* XXXX for ROUTETOIF ????? */ |
#endif |
int (*ifa_claim_addr) /* check if an addr goes to this if */ |
__P((struct ifaddr *, struct sockaddr *)); |
|
}; |
#define IFA_ROUTE RTF_UP /* route installed */ |
|
/* |
* Message format for use in obtaining information about interfaces |
* from getkerninfo and the routing socket |
*/ |
struct if_msghdr { |
u_short ifm_msglen; /* to skip over non-understood messages */ |
u_char ifm_version; /* future binary compatability */ |
u_char ifm_type; /* message type */ |
int ifm_addrs; /* like rtm_addrs */ |
int ifm_flags; /* value of if_flags */ |
u_short ifm_index; /* index for associated ifp */ |
struct if_data ifm_data;/* statistics and other data about if */ |
}; |
|
/* |
* Message format for use in obtaining information about interface addresses |
* from getkerninfo and the routing socket |
*/ |
struct ifa_msghdr { |
u_short ifam_msglen; /* to skip over non-understood messages */ |
u_char ifam_version; /* future binary compatability */ |
u_char ifam_type; /* message type */ |
int ifam_addrs; /* like rtm_addrs */ |
int ifam_flags; /* value of ifa_flags */ |
u_short ifam_index; /* index for associated ifp */ |
int ifam_metric; /* value of ifa_metric */ |
}; |
|
/* |
* Interface request structure used for socket |
* ioctl's. All interface ioctl's must have parameter |
* definitions which begin with ifr_name. The |
* remainder may be interface specific. |
*/ |
struct ifreq { |
#define IFNAMSIZ 16 |
char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */ |
union { |
struct sockaddr ifru_addr; |
struct sockaddr ifru_dstaddr; |
struct sockaddr ifru_broadaddr; |
short ifru_flags; |
int ifru_metric; |
int ifru_mtu; |
int ifru_phys; |
int ifru_media; |
caddr_t ifru_data; |
int (*ifru_tap)(struct ifnet *, struct ether_header *, struct mbuf *); |
} ifr_ifru; |
#define ifr_addr ifr_ifru.ifru_addr /* address */ |
#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-to-p link */ |
#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ |
#define ifr_flags ifr_ifru.ifru_flags /* flags */ |
#define ifr_metric ifr_ifru.ifru_metric /* metric */ |
#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ |
#define ifr_phys ifr_ifru.ifru_phys /* physical wire */ |
#define ifr_media ifr_ifru.ifru_media /* physical media */ |
#define ifr_data ifr_ifru.ifru_data /* for use by interface */ |
#define ifr_tap ifr_ifru.ifru_tap /* tap function */ |
}; |
|
struct ifaliasreq { |
char ifra_name[IFNAMSIZ]; /* if name, e.g. "en0" */ |
struct sockaddr ifra_addr; |
struct sockaddr ifra_broadaddr; |
struct sockaddr ifra_mask; |
}; |
|
struct ifmediareq { |
char ifm_name[IFNAMSIZ]; /* if name, e.g. "en0" */ |
int ifm_current; /* current media options */ |
int ifm_mask; /* don't care mask */ |
int ifm_status; /* media status */ |
int ifm_active; /* active options */ |
int ifm_count; /* # entries in ifm_ulist array */ |
int *ifm_ulist; /* media words */ |
}; |
/* |
* Structure used in SIOCGIFCONF request. |
* Used to retrieve interface configuration |
* for machine (useful for programs which |
* must know all networks accessible). |
*/ |
struct ifconf { |
int ifc_len; /* size of associated buffer */ |
union { |
caddr_t ifcu_buf; |
struct ifreq *ifcu_req; |
} ifc_ifcu; |
#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */ |
#define ifc_req ifc_ifcu.ifcu_req /* array of structures returned */ |
}; |
|
#include <net/if_arp.h> |
|
#ifdef KERNEL |
#define IFAFREE(ifa) \ |
if ((ifa)->ifa_refcnt <= 0) \ |
ifafree(ifa); \ |
else \ |
(ifa)->ifa_refcnt--; |
|
extern struct ifnet *ifnet; |
extern int ifqmaxlen; |
extern struct ifnet loif[]; |
extern int if_index; |
extern struct ifaddr **ifnet_addrs; |
|
void ether_ifattach __P((struct ifnet *)); |
void ether_input __P((struct ifnet *, struct ether_header *, struct mbuf *)); |
int ether_output __P((struct ifnet *, |
struct mbuf *, struct sockaddr *, struct rtentry *)); |
int ether_ioctl __P((struct ifnet *, int , caddr_t )); |
|
void if_attach __P((struct ifnet *)); |
void if_down __P((struct ifnet *)); |
void if_up __P((struct ifnet *)); |
#ifdef vax |
void ifubareset __P((int)); |
#endif |
/*void ifinit __P((void));*/ /* declared in systm.h for main() */ |
int ifioctl __P((struct socket *, int, caddr_t, struct proc *)); |
int ifpromisc __P((struct ifnet *, int)); |
struct ifnet *ifunit __P((char *)); |
|
int if_poll_recv_slow __P((struct ifnet *ifp, int *quotap)); |
void if_poll_xmit_slow __P((struct ifnet *ifp, int *quotap)); |
void if_poll_throttle __P((void)); |
void if_poll_unthrottle __P((void *)); |
void if_poll_init __P((void)); |
void if_poll __P((void)); |
|
struct ifaddr *ifa_ifwithaddr __P((struct sockaddr *)); |
struct ifaddr *ifa_ifwithdstaddr __P((struct sockaddr *)); |
struct ifaddr *ifa_ifwithnet __P((struct sockaddr *)); |
struct ifaddr *ifa_ifwithroute __P((int, struct sockaddr *, |
struct sockaddr *)); |
struct ifaddr *ifaof_ifpforaddr __P((struct sockaddr *, struct ifnet *)); |
void ifafree __P((struct ifaddr *)); |
|
int looutput __P((struct ifnet *, |
struct mbuf *, struct sockaddr *, struct rtentry *)); |
#endif /* KERNEL */ |
|
#endif /* !_NET_IF_H_ */ |
/rtsock.c
0,0 → 1,829
/* |
* Copyright (c) 1988, 1991, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)rtsock.c 8.5 (Berkeley) 11/2/94 |
* $Id: rtsock.c,v 1.2 2001-09-27 12:01:54 chris Exp $ |
*/ |
|
#include <sys/param.h> |
#include <sys/queue.h> |
#include <sys/systm.h> |
#include <sys/kernel.h> |
#include <sys/sysctl.h> |
#include <sys/proc.h> |
#include <sys/mbuf.h> |
#include <sys/socket.h> |
#include <sys/socketvar.h> |
#include <sys/domain.h> |
#include <sys/protosw.h> |
|
#include <net/if.h> |
#include <net/route.h> |
#include <net/raw_cb.h> |
|
static struct sockaddr route_dst = { 2, PF_ROUTE, }; |
static struct sockaddr route_src = { 2, PF_ROUTE, }; |
static struct sockaddr sa_zero = { sizeof(sa_zero), AF_INET, }; |
static struct sockproto route_proto = { PF_ROUTE, }; |
|
struct walkarg { |
int w_tmemsize; |
int w_op, w_arg; |
caddr_t w_tmem; |
struct sysctl_req *w_req; |
}; |
|
static struct mbuf * |
rt_msg1 __P((int, struct rt_addrinfo *)); |
static int rt_msg2 __P((int, |
struct rt_addrinfo *, caddr_t, struct walkarg *)); |
static int rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *)); |
static int sysctl_dumpentry __P((struct radix_node *rn, void *vw)); |
static int sysctl_iflist __P((int af, struct walkarg *w)); |
static int route_output __P((struct mbuf *, struct socket *)); |
static int route_usrreq __P((struct socket *, |
int, struct mbuf *, struct mbuf *, struct mbuf *)); |
static void rt_setmetrics __P((u_long, struct rt_metrics *, struct rt_metrics *)); |
|
/* Sleazy use of local variables throughout file, warning!!!! */ |
#define dst info.rti_info[RTAX_DST] |
#define gate info.rti_info[RTAX_GATEWAY] |
#define netmask info.rti_info[RTAX_NETMASK] |
#define genmask info.rti_info[RTAX_GENMASK] |
#define ifpaddr info.rti_info[RTAX_IFP] |
#define ifaaddr info.rti_info[RTAX_IFA] |
#define brdaddr info.rti_info[RTAX_BRD] |
|
/*ARGSUSED*/ |
static int |
route_usrreq(so, req, m, nam, control) |
register struct socket *so; |
int req; |
struct mbuf *m, *nam, *control; |
{ |
register int error = 0; |
register struct rawcb *rp = sotorawcb(so); |
int s; |
|
if (req == PRU_ATTACH) { |
MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK); |
so->so_pcb = (caddr_t)rp; |
if (so->so_pcb) |
bzero(so->so_pcb, sizeof(*rp)); |
} |
if (req == PRU_DETACH && rp) { |
int af = rp->rcb_proto.sp_protocol; |
if (af == AF_INET) |
route_cb.ip_count--; |
else if (af == AF_IPX) |
route_cb.ipx_count--; |
else if (af == AF_NS) |
route_cb.ns_count--; |
else if (af == AF_ISO) |
route_cb.iso_count--; |
route_cb.any_count--; |
} |
s = splnet(); |
error = raw_usrreq(so, req, m, nam, control); |
rp = sotorawcb(so); |
if (req == PRU_ATTACH && rp) { |
int af = rp->rcb_proto.sp_protocol; |
if (error) { |
free((caddr_t)rp, M_PCB); |
splx(s); |
return (error); |
} |
if (af == AF_INET) |
route_cb.ip_count++; |
else if (af == AF_IPX) |
route_cb.ipx_count++; |
else if (af == AF_NS) |
route_cb.ns_count++; |
else if (af == AF_ISO) |
route_cb.iso_count++; |
rp->rcb_faddr = &route_src; |
route_cb.any_count++; |
soisconnected(so); |
so->so_options |= SO_USELOOPBACK; |
} |
splx(s); |
return (error); |
} |
|
/*ARGSUSED*/ |
static int |
route_output(m, so) |
register struct mbuf *m; |
struct socket *so; |
{ |
register struct rt_msghdr *rtm = 0; |
register struct rtentry *rt = 0; |
struct rtentry *saved_nrt = 0; |
struct radix_node_head *rnh; |
struct rt_addrinfo info; |
int len, error = 0; |
struct ifnet *ifp = 0; |
struct ifaddr *ifa = 0; |
|
#define senderr(e) { error = e; goto flush;} |
if (m == 0 || ((m->m_len < sizeof(long)) && |
(m = m_pullup(m, sizeof(long))) == 0)) |
return (ENOBUFS); |
if ((m->m_flags & M_PKTHDR) == 0) |
panic("route_output"); |
len = m->m_pkthdr.len; |
if (len < sizeof(*rtm) || |
len != mtod(m, struct rt_msghdr *)->rtm_msglen) { |
dst = 0; |
senderr(EINVAL); |
} |
R_Malloc(rtm, struct rt_msghdr *, len); |
if (rtm == 0) { |
dst = 0; |
senderr(ENOBUFS); |
} |
m_copydata(m, 0, len, (caddr_t)rtm); |
if (rtm->rtm_version != RTM_VERSION) { |
dst = 0; |
senderr(EPROTONOSUPPORT); |
} |
info.rti_addrs = rtm->rtm_addrs; |
if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info)) { |
dst = 0; |
senderr(EINVAL); |
} |
if (dst == 0 || (dst->sa_family >= AF_MAX) |
|| (gate != 0 && (gate->sa_family >= AF_MAX))) |
senderr(EINVAL); |
if (genmask) { |
struct radix_node *t; |
t = rn_addmask((caddr_t)genmask, 0, 1); |
if (t && Bcmp(genmask, t->rn_key, *(u_char *)genmask) == 0) |
genmask = (struct sockaddr *)(t->rn_key); |
else |
senderr(ENOBUFS); |
} |
switch (rtm->rtm_type) { |
|
case RTM_ADD: |
if (gate == 0) |
senderr(EINVAL); |
error = rtrequest(RTM_ADD, dst, gate, netmask, |
rtm->rtm_flags, &saved_nrt); |
if (error == 0 && saved_nrt) { |
rt_setmetrics(rtm->rtm_inits, |
&rtm->rtm_rmx, &saved_nrt->rt_rmx); |
saved_nrt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); |
saved_nrt->rt_rmx.rmx_locks |= |
(rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); |
saved_nrt->rt_refcnt--; |
saved_nrt->rt_genmask = genmask; |
} |
break; |
|
case RTM_DELETE: |
error = rtrequest(RTM_DELETE, dst, gate, netmask, |
rtm->rtm_flags, &saved_nrt); |
if (error == 0) { |
if ((rt = saved_nrt)) |
rt->rt_refcnt++; |
goto report; |
} |
break; |
|
case RTM_GET: |
case RTM_CHANGE: |
case RTM_LOCK: |
if ((rnh = rt_tables[dst->sa_family]) == 0) { |
senderr(EAFNOSUPPORT); |
} else if ((rt = (struct rtentry *) |
rnh->rnh_lookup(dst, netmask, rnh))) |
rt->rt_refcnt++; |
else |
senderr(ESRCH); |
switch(rtm->rtm_type) { |
|
case RTM_GET: |
report: |
dst = rt_key(rt); |
gate = rt->rt_gateway; |
netmask = rt_mask(rt); |
genmask = rt->rt_genmask; |
if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) { |
ifp = rt->rt_ifp; |
if (ifp) { |
ifpaddr = ifp->if_addrlist->ifa_addr; |
ifaaddr = rt->rt_ifa->ifa_addr; |
rtm->rtm_index = ifp->if_index; |
} else { |
ifpaddr = 0; |
ifaaddr = 0; |
} |
} |
len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0, |
(struct walkarg *)0); |
if (len > rtm->rtm_msglen) { |
struct rt_msghdr *new_rtm; |
R_Malloc(new_rtm, struct rt_msghdr *, len); |
if (new_rtm == 0) |
senderr(ENOBUFS); |
Bcopy(rtm, new_rtm, rtm->rtm_msglen); |
Free(rtm); rtm = new_rtm; |
} |
(void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm, |
(struct walkarg *)0); |
rtm->rtm_flags = rt->rt_flags; |
rtm->rtm_rmx = rt->rt_rmx; |
rtm->rtm_addrs = info.rti_addrs; |
break; |
|
case RTM_CHANGE: |
if (gate && (error = rt_setgate(rt, rt_key(rt), gate))) |
senderr(error); |
|
/* |
* If they tried to change things but didn't specify |
* the required gateway, then just use the old one. |
* This can happen if the user tries to change the |
* flags on the default route without changing the |
* default gateway. Changing flags still doesn't work. |
*/ |
if ((rt->rt_flags & RTF_GATEWAY) && !gate) |
gate = rt->rt_gateway; |
|
/* new gateway could require new ifaddr, ifp; |
flags may also be different; ifp may be specified |
by ll sockaddr when protocol address is ambiguous */ |
if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) && |
(ifp = ifa->ifa_ifp) && (ifaaddr || gate)) |
ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate, |
ifp); |
else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) || |
(gate && (ifa = ifa_ifwithroute(rt->rt_flags, |
rt_key(rt), gate)))) |
ifp = ifa->ifa_ifp; |
if (ifa) { |
register struct ifaddr *oifa = rt->rt_ifa; |
if (oifa != ifa) { |
if (oifa && oifa->ifa_rtrequest) |
oifa->ifa_rtrequest(RTM_DELETE, |
rt, gate); |
IFAFREE(rt->rt_ifa); |
rt->rt_ifa = ifa; |
ifa->ifa_refcnt++; |
rt->rt_ifp = ifp; |
} |
} |
rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, |
&rt->rt_rmx); |
if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) |
rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate); |
if (genmask) |
rt->rt_genmask = genmask; |
/* |
* Fall into |
*/ |
case RTM_LOCK: |
rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); |
rt->rt_rmx.rmx_locks |= |
(rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); |
break; |
} |
break; |
|
default: |
senderr(EOPNOTSUPP); |
} |
|
flush: |
if (rtm) { |
if (error) |
rtm->rtm_errno = error; |
else |
rtm->rtm_flags |= RTF_DONE; |
} |
if (rt) |
rtfree(rt); |
{ |
register struct rawcb *rp = 0; |
/* |
* Check to see if we don't want our own messages. |
*/ |
if ((so->so_options & SO_USELOOPBACK) == 0) { |
if (route_cb.any_count <= 1) { |
if (rtm) |
Free(rtm); |
m_freem(m); |
return (error); |
} |
/* There is another listener, so construct message */ |
rp = sotorawcb(so); |
} |
if (rtm) { |
m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm); |
Free(rtm); |
} |
if (rp) |
rp->rcb_proto.sp_family = 0; /* Avoid us */ |
if (dst) |
route_proto.sp_protocol = dst->sa_family; |
raw_input(m, &route_proto, &route_src, &route_dst); |
if (rp) |
rp->rcb_proto.sp_family = PF_ROUTE; |
} |
return (error); |
} |
|
static void |
rt_setmetrics(which, in, out) |
u_long which; |
register struct rt_metrics *in, *out; |
{ |
#define metric(f, e) if (which & (f)) out->e = in->e; |
metric(RTV_RPIPE, rmx_recvpipe); |
metric(RTV_SPIPE, rmx_sendpipe); |
metric(RTV_SSTHRESH, rmx_ssthresh); |
metric(RTV_RTT, rmx_rtt); |
metric(RTV_RTTVAR, rmx_rttvar); |
metric(RTV_HOPCOUNT, rmx_hopcount); |
metric(RTV_MTU, rmx_mtu); |
metric(RTV_EXPIRE, rmx_expire); |
#undef metric |
} |
|
#define ROUNDUP(a) \ |
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) |
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) |
|
|
/* |
* Extract the addresses of the passed sockaddrs. |
* Do a little sanity checking so as to avoid bad memory references. |
* This data is derived straight from userland. |
*/ |
static int |
rt_xaddrs(cp, cplim, rtinfo) |
register caddr_t cp, cplim; |
register struct rt_addrinfo *rtinfo; |
{ |
register struct sockaddr *sa; |
register int i; |
|
bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info)); |
for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { |
if ((rtinfo->rti_addrs & (1 << i)) == 0) |
continue; |
sa = (struct sockaddr *)cp; |
/* |
* It won't fit. |
*/ |
if ( (cp + sa->sa_len) > cplim ) { |
return (EINVAL); |
} |
|
/* |
* there are no more.. quit now |
* If there are more bits, they are in error. |
* I've seen this. route(1) can evidently generate these. |
* This causes kernel to core dump. |
* for compatibility, If we see this, point to a safe address. |
*/ |
if (sa->sa_len == 0) { |
rtinfo->rti_info[i] = &sa_zero; |
return (0); /* should be EINVAL but for compat */ |
} |
|
/* accept it */ |
rtinfo->rti_info[i] = sa; |
ADVANCE(cp, sa); |
} |
return (0); |
} |
|
static struct mbuf * |
rt_msg1(type, rtinfo) |
int type; |
register struct rt_addrinfo *rtinfo; |
{ |
register struct rt_msghdr *rtm; |
register struct mbuf *m; |
register int i; |
register struct sockaddr *sa; |
int len, dlen; |
|
m = m_gethdr(M_DONTWAIT, MT_DATA); |
if (m == 0) |
return (m); |
switch (type) { |
|
case RTM_DELADDR: |
case RTM_NEWADDR: |
len = sizeof(struct ifa_msghdr); |
break; |
|
case RTM_IFINFO: |
len = sizeof(struct if_msghdr); |
break; |
|
default: |
len = sizeof(struct rt_msghdr); |
} |
if (len > MHLEN) |
panic("rt_msg1"); |
m->m_pkthdr.len = m->m_len = len; |
m->m_pkthdr.rcvif = 0; |
rtm = mtod(m, struct rt_msghdr *); |
bzero((caddr_t)rtm, len); |
for (i = 0; i < RTAX_MAX; i++) { |
if ((sa = rtinfo->rti_info[i]) == NULL) |
continue; |
rtinfo->rti_addrs |= (1 << i); |
dlen = ROUNDUP(sa->sa_len); |
m_copyback(m, len, dlen, (caddr_t)sa); |
len += dlen; |
} |
if (m->m_pkthdr.len != len) { |
m_freem(m); |
return (NULL); |
} |
rtm->rtm_msglen = len; |
rtm->rtm_version = RTM_VERSION; |
rtm->rtm_type = type; |
return (m); |
} |
|
static int |
rt_msg2(type, rtinfo, cp, w) |
int type; |
register struct rt_addrinfo *rtinfo; |
caddr_t cp; |
struct walkarg *w; |
{ |
register int i; |
int len, dlen, second_time = 0; |
caddr_t cp0; |
|
rtinfo->rti_addrs = 0; |
again: |
switch (type) { |
|
case RTM_DELADDR: |
case RTM_NEWADDR: |
len = sizeof(struct ifa_msghdr); |
break; |
|
case RTM_IFINFO: |
len = sizeof(struct if_msghdr); |
break; |
|
default: |
len = sizeof(struct rt_msghdr); |
} |
cp0 = cp; |
if (cp0) |
cp += len; |
for (i = 0; i < RTAX_MAX; i++) { |
register struct sockaddr *sa; |
|
if ((sa = rtinfo->rti_info[i]) == 0) |
continue; |
rtinfo->rti_addrs |= (1 << i); |
dlen = ROUNDUP(sa->sa_len); |
if (cp) { |
bcopy((caddr_t)sa, cp, (unsigned)dlen); |
cp += dlen; |
} |
len += dlen; |
} |
if (cp == 0 && w != NULL && !second_time) { |
register struct walkarg *rw = w; |
|
if (rw->w_req) { |
if (rw->w_tmemsize < len) { |
if (rw->w_tmem) |
free(rw->w_tmem, M_RTABLE); |
rw->w_tmem = (caddr_t) |
malloc(len, M_RTABLE, M_NOWAIT); |
if (rw->w_tmem) |
rw->w_tmemsize = len; |
} |
if (rw->w_tmem) { |
cp = rw->w_tmem; |
second_time = 1; |
goto again; |
} |
} |
} |
if (cp) { |
register struct rt_msghdr *rtm = (struct rt_msghdr *)cp0; |
|
rtm->rtm_version = RTM_VERSION; |
rtm->rtm_type = type; |
rtm->rtm_msglen = len; |
} |
return (len); |
} |
|
/* |
* This routine is called to generate a message from the routing |
* socket indicating that a redirect has occured, a routing lookup |
* has failed, or that a protocol has detected timeouts to a particular |
* destination. |
*/ |
void |
rt_missmsg(type, rtinfo, flags, error) |
int type, flags, error; |
register struct rt_addrinfo *rtinfo; |
{ |
register struct rt_msghdr *rtm; |
register struct mbuf *m; |
struct sockaddr *sa = rtinfo->rti_info[RTAX_DST]; |
|
if (route_cb.any_count == 0) |
return; |
m = rt_msg1(type, rtinfo); |
if (m == 0) |
return; |
rtm = mtod(m, struct rt_msghdr *); |
rtm->rtm_flags = RTF_DONE | flags; |
rtm->rtm_errno = error; |
rtm->rtm_addrs = rtinfo->rti_addrs; |
route_proto.sp_protocol = sa ? sa->sa_family : 0; |
raw_input(m, &route_proto, &route_src, &route_dst); |
} |
|
/* |
* This routine is called to generate a message from the routing |
* socket indicating that the status of a network interface has changed. |
*/ |
void |
rt_ifmsg(ifp) |
register struct ifnet *ifp; |
{ |
register struct if_msghdr *ifm; |
struct mbuf *m; |
struct rt_addrinfo info; |
|
if (route_cb.any_count == 0) |
return; |
bzero((caddr_t)&info, sizeof(info)); |
m = rt_msg1(RTM_IFINFO, &info); |
if (m == 0) |
return; |
ifm = mtod(m, struct if_msghdr *); |
ifm->ifm_index = ifp->if_index; |
ifm->ifm_flags = (u_short)ifp->if_flags; |
ifm->ifm_data = ifp->if_data; |
ifm->ifm_addrs = 0; |
route_proto.sp_protocol = 0; |
raw_input(m, &route_proto, &route_src, &route_dst); |
} |
|
/* |
* This is called to generate messages from the routing socket |
* indicating a network interface has had addresses associated with it. |
* if we ever reverse the logic and replace messages TO the routing |
* socket indicate a request to configure interfaces, then it will |
* be unnecessary as the routing socket will automatically generate |
* copies of it. |
*/ |
void |
rt_newaddrmsg(cmd, ifa, error, rt) |
int cmd, error; |
register struct ifaddr *ifa; |
register struct rtentry *rt; |
{ |
struct rt_addrinfo info; |
struct sockaddr *sa = 0; |
int pass; |
struct mbuf *m = 0; |
struct ifnet *ifp = ifa->ifa_ifp; |
|
if (route_cb.any_count == 0) |
return; |
for (pass = 1; pass < 3; pass++) { |
bzero((caddr_t)&info, sizeof(info)); |
if ((cmd == RTM_ADD && pass == 1) || |
(cmd == RTM_DELETE && pass == 2)) { |
register struct ifa_msghdr *ifam; |
int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR; |
|
ifaaddr = sa = ifa->ifa_addr; |
ifpaddr = ifp->if_addrlist->ifa_addr; |
netmask = ifa->ifa_netmask; |
brdaddr = ifa->ifa_dstaddr; |
if ((m = rt_msg1(ncmd, &info)) == NULL) |
continue; |
ifam = mtod(m, struct ifa_msghdr *); |
ifam->ifam_index = ifp->if_index; |
ifam->ifam_metric = ifa->ifa_metric; |
ifam->ifam_flags = ifa->ifa_flags; |
ifam->ifam_addrs = info.rti_addrs; |
} |
if ((cmd == RTM_ADD && pass == 2) || |
(cmd == RTM_DELETE && pass == 1)) { |
register struct rt_msghdr *rtm; |
|
if (rt == 0) |
continue; |
netmask = rt_mask(rt); |
dst = sa = rt_key(rt); |
gate = rt->rt_gateway; |
if ((m = rt_msg1(cmd, &info)) == NULL) |
continue; |
rtm = mtod(m, struct rt_msghdr *); |
rtm->rtm_index = ifp->if_index; |
rtm->rtm_flags |= rt->rt_flags; |
rtm->rtm_errno = error; |
rtm->rtm_addrs = info.rti_addrs; |
} |
route_proto.sp_protocol = sa ? sa->sa_family : 0; |
raw_input(m, &route_proto, &route_src, &route_dst); |
} |
} |
|
|
/* |
* This is used in dumping the kernel table via sysctl(). |
*/ |
int |
sysctl_dumpentry(rn, vw) |
struct radix_node *rn; |
void *vw; |
{ |
register struct walkarg *w = vw; |
register struct rtentry *rt = (struct rtentry *)rn; |
int error = 0, size; |
struct rt_addrinfo info; |
|
if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) |
return 0; |
bzero((caddr_t)&info, sizeof(info)); |
dst = rt_key(rt); |
gate = rt->rt_gateway; |
netmask = rt_mask(rt); |
genmask = rt->rt_genmask; |
size = rt_msg2(RTM_GET, &info, 0, w); |
if (w->w_req && w->w_tmem) { |
register struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem; |
|
rtm->rtm_flags = rt->rt_flags; |
rtm->rtm_use = rt->rt_use; |
rtm->rtm_rmx = rt->rt_rmx; |
rtm->rtm_index = rt->rt_ifp->if_index; |
rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0; |
rtm->rtm_addrs = info.rti_addrs; |
error = 0; |
return (error); |
} |
return (error); |
} |
|
int |
sysctl_iflist(af, w) |
int af; |
register struct walkarg *w; |
{ |
register struct ifnet *ifp; |
register struct ifaddr *ifa; |
struct rt_addrinfo info; |
int len, error = 0; |
|
bzero((caddr_t)&info, sizeof(info)); |
for (ifp = ifnet; ifp; ifp = ifp->if_next) { |
if (w->w_arg && w->w_arg != ifp->if_index) |
continue; |
ifa = ifp->if_addrlist; |
ifpaddr = ifa->ifa_addr; |
len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w); |
ifpaddr = 0; |
if (w->w_req && w->w_tmem) { |
register struct if_msghdr *ifm; |
|
ifm = (struct if_msghdr *)w->w_tmem; |
ifm->ifm_index = ifp->if_index; |
ifm->ifm_flags = (u_short)ifp->if_flags; |
ifm->ifm_data = ifp->if_data; |
ifm->ifm_addrs = info.rti_addrs; |
error =0; |
if (error) |
return (error); |
} |
while ((ifa = ifa->ifa_next) != 0) { |
if (af && af != ifa->ifa_addr->sa_family) |
continue; |
ifaaddr = ifa->ifa_addr; |
netmask = ifa->ifa_netmask; |
brdaddr = ifa->ifa_dstaddr; |
len = rt_msg2(RTM_NEWADDR, &info, 0, w); |
if (w->w_req && w->w_tmem) { |
register struct ifa_msghdr *ifam; |
|
ifam = (struct ifa_msghdr *)w->w_tmem; |
ifam->ifam_index = ifa->ifa_ifp->if_index; |
ifam->ifam_flags = ifa->ifa_flags; |
ifam->ifam_metric = ifa->ifa_metric; |
ifam->ifam_addrs = info.rti_addrs; |
error = 0; |
if (error) |
return (error); |
} |
} |
ifaaddr = netmask = brdaddr = 0; |
} |
return (0); |
} |
|
static int |
sysctl_rtsock SYSCTL_HANDLER_ARGS |
{ |
int *name = (int *)arg1; |
u_int namelen = arg2; |
register struct radix_node_head *rnh; |
int i, s, error = EINVAL; |
u_char af; |
struct walkarg w; |
|
name ++; |
namelen--; |
if (req->newptr) |
return (EPERM); |
if (namelen != 3) |
return (EINVAL); |
af = name[0]; |
Bzero(&w, sizeof(w)); |
w.w_op = name[1]; |
w.w_arg = name[2]; |
w.w_req = req; |
|
s = splnet(); |
switch (w.w_op) { |
|
case NET_RT_DUMP: |
case NET_RT_FLAGS: |
for (i = 1; i <= AF_MAX; i++) |
if ((rnh = rt_tables[i]) && (af == 0 || af == i) && |
(error = rnh->rnh_walktree(rnh, |
sysctl_dumpentry, &w))) |
break; |
break; |
|
case NET_RT_IFLIST: |
error = sysctl_iflist(af, &w); |
} |
splx(s); |
if (w.w_tmem) |
free(w.w_tmem, M_RTABLE); |
return (error); |
} |
|
SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock,""); |
|
/* |
* Definitions of protocols supported in the ROUTE domain. |
*/ |
|
extern struct domain routedomain; /* or at least forward */ |
|
static struct protosw routesw[] = { |
{ SOCK_RAW, &routedomain, 0, PR_ATOMIC|PR_ADDR, |
0, route_output, raw_ctlinput, 0, |
route_usrreq, |
raw_init |
} |
}; |
|
struct domain routedomain = |
{ PF_ROUTE, "route", route_init, 0, 0, |
routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])] }; |
|
DOMAIN_SET(route); |
/if_arp.h
0,0 → 1,91
/* |
* Copyright (c) 1986, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)if_arp.h 8.1 (Berkeley) 6/10/93 |
* $Id: if_arp.h,v 1.2 2001-09-27 12:01:54 chris Exp $ |
*/ |
|
#ifndef _NET_IF_ARP_H_ |
#define _NET_IF_ARP_H_ |
|
/* |
* Address Resolution Protocol. |
* |
* See RFC 826 for protocol description. ARP packets are variable |
* in size; the arphdr structure defines the fixed-length portion. |
* Protocol type values are the same as those for 10 Mb/s Ethernet. |
* It is followed by the variable-sized fields ar_sha, arp_spa, |
* arp_tha and arp_tpa in that order, according to the lengths |
* specified. Field names used correspond to RFC 826. |
*/ |
struct arphdr { |
u_short ar_hrd; /* format of hardware address */ |
#define ARPHRD_ETHER 1 /* ethernet hardware format */ |
#define ARPHRD_FRELAY 15 /* frame relay hardware format */ |
u_short ar_pro; /* format of protocol address */ |
u_char ar_hln; /* length of hardware address */ |
u_char ar_pln; /* length of protocol address */ |
u_short ar_op; /* one of: */ |
#define ARPOP_REQUEST 1 /* request to resolve address */ |
#define ARPOP_REPLY 2 /* response to previous request */ |
#define ARPOP_REVREQUEST 3 /* request protocol address given hardware */ |
#define ARPOP_REVREPLY 4 /* response giving protocol address */ |
#define ARPOP_INVREQUEST 8 /* request to identify peer */ |
#define ARPOP_INVREPLY 9 /* response identifying peer */ |
/* |
* The remaining fields are variable in size, |
* according to the sizes above. |
*/ |
#ifdef COMMENT_ONLY |
u_char ar_sha[]; /* sender hardware address */ |
u_char ar_spa[]; /* sender protocol address */ |
u_char ar_tha[]; /* target hardware address */ |
u_char ar_tpa[]; /* target protocol address */ |
#endif |
}; |
|
/* |
* ARP ioctl request |
*/ |
struct arpreq { |
struct sockaddr arp_pa; /* protocol address */ |
struct sockaddr arp_ha; /* hardware address */ |
int arp_flags; /* flags */ |
}; |
/* arp_flags and at_flags field values */ |
#define ATF_INUSE 0x01 /* entry in use */ |
#define ATF_COM 0x02 /* completed entry (enaddr valid) */ |
#define ATF_PERM 0x04 /* permanent entry */ |
#define ATF_PUBL 0x08 /* publish entry (respond for other host) */ |
#define ATF_USETRAILERS 0x10 /* has requested trailers */ |
|
#endif /* !_NET_IF_ARP_H_ */ |
/ppp_defs.h
0,0 → 1,183
/* $Id: ppp_defs.h,v 1.2 2001-09-27 12:01:54 chris Exp $ */ |
|
/* |
* ppp_defs.h - PPP definitions. |
* |
* Copyright (c) 1994 The Australian National University. |
* All rights reserved. |
* |
* Permission to use, copy, modify, and distribute this software and its |
* documentation is hereby granted, provided that the above copyright |
* notice appears in all copies. This software is provided without any |
* warranty, express or implied. The Australian National University |
* makes no representations about the suitability of this software for |
* any purpose. |
* |
* IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY |
* PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF |
* THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY |
* OF SUCH DAMAGE. |
* |
* THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, |
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY |
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
* ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO |
* OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, |
* OR MODIFICATIONS. |
*/ |
|
#ifndef _PPP_DEFS_H_ |
#define _PPP_DEFS_H_ |
|
/* |
* The basic PPP frame. |
*/ |
#define PPP_HDRLEN 4 /* octets for standard ppp header */ |
#define PPP_FCSLEN 2 /* octets for FCS */ |
|
/* |
* Packet sizes |
* |
* Note - lcp shouldn't be allowed to negotiate stuff outside these |
* limits. See lcp.h in the pppd directory. |
* (XXX - these constants should simply be shared by lcp.c instead |
* of living in lcp.h) |
*/ |
#define PPP_MTU 1500 /* Default MTU (size of Info field) */ |
#define PPP_MAXMTU 65535 - (PPP_HDRLEN + PPP_FCSLEN) |
#define PPP_MINMTU 64 |
#define PPP_MRU 1500 /* default MRU = max length of info field */ |
#define PPP_MAXMRU 65000 /* Largest MRU we allow */ |
#define PPP_MINMRU 128 |
|
#define PPP_ADDRESS(p) (((u_char *)(p))[0]) |
#define PPP_CONTROL(p) (((u_char *)(p))[1]) |
#define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3]) |
|
/* |
* Significant octet values. |
*/ |
#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ |
#define PPP_UI 0x03 /* Unnumbered Information */ |
#define PPP_FLAG 0x7e /* Flag Sequence */ |
#define PPP_ESCAPE 0x7d /* Asynchronous Control Escape */ |
#define PPP_TRANS 0x20 /* Asynchronous transparency modifier */ |
|
/* |
* Protocol field values. |
*/ |
#define PPP_IP 0x21 /* Internet Protocol */ |
#define PPP_AT 0x29 /* AppleTalk Protocol */ |
#define PPP_IPX 0x2b /* IPX protocol */ |
#define PPP_VJC_COMP 0x2d /* VJ compressed TCP */ |
#define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */ |
#define PPP_IPV6 0x57 /* Internet Protocol Version 6 */ |
#define PPP_COMP 0xfd /* compressed packet */ |
#define PPP_IPCP 0x8021 /* IP Control Protocol */ |
#define PPP_ATCP 0x8029 /* AppleTalk Control Protocol */ |
#define PPP_IPXCP 0x802b /* IPX Control Protocol */ |
#define PPP_CCP 0x80fd /* Compression Control Protocol */ |
#define PPP_LCP 0xc021 /* Link Control Protocol */ |
#define PPP_PAP 0xc023 /* Password Authentication Protocol */ |
#define PPP_LQR 0xc025 /* Link Quality Report protocol */ |
#define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */ |
#define PPP_CBCP 0xc029 /* Callback Control Protocol */ |
|
/* |
* Values for FCS calculations. |
*/ |
#define PPP_INITFCS 0xffff /* Initial FCS value */ |
#define PPP_GOODFCS 0xf0b8 /* Good final FCS value */ |
#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff]) |
|
/* |
* A 32-bit unsigned integral type. |
*/ |
|
#if !defined(__BIT_TYPES_DEFINED__) && !defined(_BITYPES) \ |
&& !defined(__FreeBSD__) && (NS_TARGET < 40) && !defined(__rtems__) |
#ifdef UINT32_T |
typedef UINT32_T u_int32_t; |
#else |
typedef unsigned int u_int32_t; |
typedef unsigned short u_int16_t; |
#endif |
#endif |
|
/* |
* Extended asyncmap - allows any character to be escaped. |
*/ |
typedef u_int32_t ext_accm[8]; |
|
/* |
* What to do with network protocol (NP) packets. |
*/ |
enum NPmode { |
NPMODE_PASS, /* pass the packet through */ |
NPMODE_DROP, /* silently drop the packet */ |
NPMODE_ERROR, /* return an error */ |
NPMODE_QUEUE /* save it up for later. */ |
}; |
|
/* |
* Statistics. |
*/ |
struct pppstat { |
unsigned int ppp_ibytes; /* bytes received */ |
unsigned int ppp_ipackets; /* packets received */ |
unsigned int ppp_ierrors; /* receive errors */ |
unsigned int ppp_obytes; /* bytes sent */ |
unsigned int ppp_opackets; /* packets sent */ |
unsigned int ppp_oerrors; /* transmit errors */ |
}; |
|
struct vjstat { |
unsigned int vjs_packets; /* outbound packets */ |
unsigned int vjs_compressed; /* outbound compressed packets */ |
unsigned int vjs_searches; /* searches for connection state */ |
unsigned int vjs_misses; /* times couldn't find conn. state */ |
unsigned int vjs_uncompressedin; /* inbound uncompressed packets */ |
unsigned int vjs_compressedin; /* inbound compressed packets */ |
unsigned int vjs_errorin; /* inbound unknown type packets */ |
unsigned int vjs_tossed; /* inbound packets tossed because of error */ |
}; |
|
struct ppp_stats { |
struct pppstat p; /* basic PPP statistics */ |
struct vjstat vj; /* VJ header compression statistics */ |
}; |
|
struct compstat { |
unsigned int unc_bytes; /* total uncompressed bytes */ |
unsigned int unc_packets; /* total uncompressed packets */ |
unsigned int comp_bytes; /* compressed bytes */ |
unsigned int comp_packets; /* compressed packets */ |
unsigned int inc_bytes; /* incompressible bytes */ |
unsigned int inc_packets; /* incompressible packets */ |
unsigned int ratio; /* recent compression ratio << 8 */ |
}; |
|
struct ppp_comp_stats { |
struct compstat c; /* packet compression statistics */ |
struct compstat d; /* packet decompression statistics */ |
}; |
|
/* |
* The following structure records the time in seconds since |
* the last NP packet was sent or received. |
*/ |
struct ppp_idle { |
time_t xmit_idle; /* time since last NP packet sent */ |
time_t recv_idle; /* time since last NP packet received */ |
}; |
|
#ifndef __P |
#ifdef __STDC__ |
#define __P(x) x |
#else |
#define __P(x) () |
#endif |
#endif |
|
#endif /* _PPP_DEFS_H_ */ |
/radix.c
0,0 → 1,1028
/* |
* Copyright (c) 1988, 1989, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)radix.c 8.4 (Berkeley) 11/2/94 |
* $Id: radix.c,v 1.2 2001-09-27 12:01:54 chris Exp $ |
*/ |
|
/* |
* Routines to build and maintain radix trees for routing lookups. |
*/ |
#ifndef _RADIX_H_ |
#include <sys/param.h> |
#ifdef KERNEL |
#include <sys/systm.h> |
#include <sys/malloc.h> |
#define M_DONTWAIT M_NOWAIT |
#include <sys/domain.h> |
#else |
#include <stdlib.h> |
#endif |
#include <sys/syslog.h> |
#include <net/radix.h> |
#endif |
|
static struct radix_node * |
rn_lookup __P((void *v_arg, void *m_arg, |
struct radix_node_head *head)); |
static int rn_walktree_from __P((struct radix_node_head *h, void *a, |
void *m, walktree_f_t *f, void *w)); |
static int rn_walktree __P((struct radix_node_head *, walktree_f_t *, void *)); |
static struct radix_node |
*rn_delete __P((void *, void *, struct radix_node_head *)), |
*rn_insert __P((void *, struct radix_node_head *, int *, |
struct radix_node [2])), |
*rn_newpair __P((void *, int, struct radix_node[2])), |
*rn_search __P((void *, struct radix_node *)), |
*rn_search_m __P((void *, struct radix_node *, void *)); |
|
static int max_keylen; |
static struct radix_mask *rn_mkfreelist; |
static struct radix_node_head *mask_rnhead; |
static char *addmask_key; |
static char normal_chars[] = {0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, -1}; |
static char *rn_zeros, *rn_ones; |
|
#define rn_masktop (mask_rnhead->rnh_treetop) |
#undef Bcmp |
#define Bcmp(a, b, l) (l == 0 ? 0 : bcmp((caddr_t)(a), (caddr_t)(b), (u_long)l)) |
|
static int rn_lexobetter __P((void *m_arg, void *n_arg)); |
static struct radix_mask * |
rn_new_radix_mask __P((struct radix_node *tt, |
struct radix_mask *next)); |
static int rn_satsifies_leaf __P((char *trial, struct radix_node *leaf, |
int skip)); |
|
/* |
* The data structure for the keys is a radix tree with one way |
* branching removed. The index rn_b at an internal node n represents a bit |
* position to be tested. The tree is arranged so that all descendants |
* of a node n have keys whose bits all agree up to position rn_b - 1. |
* (We say the index of n is rn_b.) |
* |
* There is at least one descendant which has a one bit at position rn_b, |
* and at least one with a zero there. |
* |
* A route is determined by a pair of key and mask. We require that the |
* bit-wise logical and of the key and mask to be the key. |
* We define the index of a route to associated with the mask to be |
* the first bit number in the mask where 0 occurs (with bit number 0 |
* representing the highest order bit). |
* |
* We say a mask is normal if every bit is 0, past the index of the mask. |
* If a node n has a descendant (k, m) with index(m) == index(n) == rn_b, |
* and m is a normal mask, then the route applies to every descendant of n. |
* If the index(m) < rn_b, this implies the trailing last few bits of k |
* before bit b are all 0, (and hence consequently true of every descendant |
* of n), so the route applies to all descendants of the node as well. |
* |
* Similar logic shows that a non-normal mask m such that |
* index(m) <= index(n) could potentially apply to many children of n. |
* Thus, for each non-host route, we attach its mask to a list at an internal |
* node as high in the tree as we can go. |
* |
* The present version of the code makes use of normal routes in short- |
* circuiting an explict mask and compare operation when testing whether |
* a key satisfies a normal route, and also in remembering the unique leaf |
* that governs a subtree. |
*/ |
|
static struct radix_node * |
rn_search(v_arg, head) |
void *v_arg; |
struct radix_node *head; |
{ |
register struct radix_node *x; |
register caddr_t v; |
|
for (x = head, v = v_arg; x->rn_b >= 0;) { |
if (x->rn_bmask & v[x->rn_off]) |
x = x->rn_r; |
else |
x = x->rn_l; |
} |
return (x); |
}; |
|
static struct radix_node * |
rn_search_m(v_arg, head, m_arg) |
struct radix_node *head; |
void *v_arg, *m_arg; |
{ |
register struct radix_node *x; |
register caddr_t v = v_arg, m = m_arg; |
|
for (x = head; x->rn_b >= 0;) { |
if ((x->rn_bmask & m[x->rn_off]) && |
(x->rn_bmask & v[x->rn_off])) |
x = x->rn_r; |
else |
x = x->rn_l; |
} |
return x; |
}; |
|
int |
rn_refines(m_arg, n_arg) |
void *m_arg, *n_arg; |
{ |
register caddr_t m = m_arg, n = n_arg; |
register caddr_t lim, lim2 = lim = n + *(u_char *)n; |
int longer = (*(u_char *)n++) - (int)(*(u_char *)m++); |
int masks_are_equal = 1; |
|
if (longer > 0) |
lim -= longer; |
while (n < lim) { |
if (*n & ~(*m)) |
return 0; |
if (*n++ != *m++) |
masks_are_equal = 0; |
} |
while (n < lim2) |
if (*n++) |
return 0; |
if (masks_are_equal && (longer < 0)) |
for (lim2 = m - longer; m < lim2; ) |
if (*m++) |
return 1; |
return (!masks_are_equal); |
} |
|
struct radix_node * |
rn_lookup(v_arg, m_arg, head) |
void *v_arg, *m_arg; |
struct radix_node_head *head; |
{ |
register struct radix_node *x; |
caddr_t netmask = 0; |
|
if (m_arg) { |
if ((x = rn_addmask(m_arg, 1, head->rnh_treetop->rn_off)) == 0) |
return (0); |
netmask = x->rn_key; |
} |
x = rn_match(v_arg, head); |
if (x && netmask) { |
while (x && x->rn_mask != netmask) |
x = x->rn_dupedkey; |
} |
return x; |
} |
|
static int |
rn_satsifies_leaf(trial, leaf, skip) |
char *trial; |
register struct radix_node *leaf; |
int skip; |
{ |
register char *cp = trial, *cp2 = leaf->rn_key, *cp3 = leaf->rn_mask; |
char *cplim; |
int length = min(*(u_char *)cp, *(u_char *)cp2); |
|
if (cp3 == 0) |
cp3 = rn_ones; |
else |
length = min(length, *(u_char *)cp3); |
cplim = cp + length; cp3 += skip; cp2 += skip; |
for (cp += skip; cp < cplim; cp++, cp2++, cp3++) |
if ((*cp ^ *cp2) & *cp3) |
return 0; |
return 1; |
} |
|
struct radix_node * |
rn_match(v_arg, head) |
void *v_arg; |
struct radix_node_head *head; |
{ |
caddr_t v = v_arg; |
register struct radix_node *t = head->rnh_treetop, *x; |
register caddr_t cp = v, cp2; |
caddr_t cplim; |
struct radix_node *saved_t, *top = t; |
int off = t->rn_off, vlen = *(u_char *)cp, matched_off; |
register int test, b, rn_b; |
|
/* |
* Open code rn_search(v, top) to avoid overhead of extra |
* subroutine call. |
*/ |
for (; t->rn_b >= 0; ) { |
if (t->rn_bmask & cp[t->rn_off]) |
t = t->rn_r; |
else |
t = t->rn_l; |
} |
/* |
* See if we match exactly as a host destination |
* or at least learn how many bits match, for normal mask finesse. |
* |
* It doesn't hurt us to limit how many bytes to check |
* to the length of the mask, since if it matches we had a genuine |
* match and the leaf we have is the most specific one anyway; |
* if it didn't match with a shorter length it would fail |
* with a long one. This wins big for class B&C netmasks which |
* are probably the most common case... |
*/ |
if (t->rn_mask) |
vlen = *(u_char *)t->rn_mask; |
cp += off; cp2 = t->rn_key + off; cplim = v + vlen; |
for (; cp < cplim; cp++, cp2++) |
if (*cp != *cp2) |
goto on1; |
/* |
* This extra grot is in case we are explicitly asked |
* to look up the default. Ugh! |
*/ |
if ((t->rn_flags & RNF_ROOT) && t->rn_dupedkey) |
t = t->rn_dupedkey; |
return t; |
on1: |
test = (*cp ^ *cp2) & 0xff; /* find first bit that differs */ |
for (b = 7; (test >>= 1) > 0;) |
b--; |
matched_off = cp - v; |
b += matched_off << 3; |
rn_b = -1 - b; |
/* |
* If there is a host route in a duped-key chain, it will be first. |
*/ |
if ((saved_t = t)->rn_mask == 0) |
t = t->rn_dupedkey; |
for (; t; t = t->rn_dupedkey) |
/* |
* Even if we don't match exactly as a host, |
* we may match if the leaf we wound up at is |
* a route to a net. |
*/ |
if (t->rn_flags & RNF_NORMAL) { |
if (rn_b <= t->rn_b) |
return t; |
} else if (rn_satsifies_leaf(v, t, matched_off)) |
return t; |
t = saved_t; |
/* start searching up the tree */ |
do { |
register struct radix_mask *m; |
t = t->rn_p; |
m = t->rn_mklist; |
if (m) { |
/* |
* If non-contiguous masks ever become important |
* we can restore the masking and open coding of |
* the search and satisfaction test and put the |
* calculation of "off" back before the "do". |
*/ |
do { |
if (m->rm_flags & RNF_NORMAL) { |
if (rn_b <= m->rm_b) |
return (m->rm_leaf); |
} else { |
off = min(t->rn_off, matched_off); |
x = rn_search_m(v, t, m->rm_mask); |
while (x && x->rn_mask != m->rm_mask) |
x = x->rn_dupedkey; |
if (x && rn_satsifies_leaf(v, x, off)) |
return x; |
} |
m = m->rm_mklist; |
} while (m); |
} |
} while (t != top); |
return 0; |
}; |
|
#ifdef RN_DEBUG |
int rn_nodenum; |
struct radix_node *rn_clist; |
int rn_saveinfo; |
int rn_debug = 1; |
#endif |
|
static struct radix_node * |
rn_newpair(v, b, nodes) |
void *v; |
int b; |
struct radix_node nodes[2]; |
{ |
register struct radix_node *tt = nodes, *t = tt + 1; |
t->rn_b = b; t->rn_bmask = 0x80 >> (b & 7); |
t->rn_l = tt; t->rn_off = b >> 3; |
tt->rn_b = -1; tt->rn_key = (caddr_t)v; tt->rn_p = t; |
tt->rn_flags = t->rn_flags = RNF_ACTIVE; |
#ifdef RN_DEBUG |
tt->rn_info = rn_nodenum++; t->rn_info = rn_nodenum++; |
tt->rn_twin = t; tt->rn_ybro = rn_clist; rn_clist = tt; |
#endif |
return t; |
} |
|
static struct radix_node * |
rn_insert(v_arg, head, dupentry, nodes) |
void *v_arg; |
struct radix_node_head *head; |
int *dupentry; |
struct radix_node nodes[2]; |
{ |
caddr_t v = v_arg; |
struct radix_node *top = head->rnh_treetop; |
int head_off = top->rn_off, vlen = (int)*((u_char *)v); |
register struct radix_node *t = rn_search(v_arg, top); |
register caddr_t cp = v + head_off; |
register int b; |
struct radix_node *tt; |
/* |
* Find first bit at which v and t->rn_key differ |
*/ |
{ |
register caddr_t cp2 = t->rn_key + head_off; |
register int cmp_res; |
caddr_t cplim = v + vlen; |
|
while (cp < cplim) |
if (*cp2++ != *cp++) |
goto on1; |
*dupentry = 1; |
return t; |
on1: |
*dupentry = 0; |
cmp_res = (cp[-1] ^ cp2[-1]) & 0xff; |
for (b = (cp - v) << 3; cmp_res; b--) |
cmp_res >>= 1; |
} |
{ |
register struct radix_node *p, *x = top; |
cp = v; |
do { |
p = x; |
if (cp[x->rn_off] & x->rn_bmask) |
x = x->rn_r; |
else x = x->rn_l; |
} while (b > (unsigned) x->rn_b); /* x->rn_b < b && x->rn_b >= 0 */ |
#ifdef RN_DEBUG |
if (rn_debug) |
log(LOG_DEBUG, "rn_insert: Going In:\n"), traverse(p); |
#endif |
t = rn_newpair(v_arg, b, nodes); tt = t->rn_l; |
if ((cp[p->rn_off] & p->rn_bmask) == 0) |
p->rn_l = t; |
else |
p->rn_r = t; |
x->rn_p = t; t->rn_p = p; /* frees x, p as temp vars below */ |
if ((cp[t->rn_off] & t->rn_bmask) == 0) { |
t->rn_r = x; |
} else { |
t->rn_r = tt; t->rn_l = x; |
} |
#ifdef RN_DEBUG |
if (rn_debug) |
log(LOG_DEBUG, "rn_insert: Coming Out:\n"), traverse(p); |
#endif |
} |
return (tt); |
} |
|
struct radix_node * |
rn_addmask(n_arg, search, skip) |
int search, skip; |
void *n_arg; |
{ |
caddr_t netmask = (caddr_t)n_arg; |
register struct radix_node *x; |
register caddr_t cp, cplim; |
register int b = 0, mlen, j; |
int maskduplicated, m0, isnormal; |
struct radix_node *saved_x; |
static int last_zeroed = 0; |
|
if ((mlen = *(u_char *)netmask) > max_keylen) |
mlen = max_keylen; |
if (skip == 0) |
skip = 1; |
if (mlen <= skip) |
return (mask_rnhead->rnh_nodes); |
if (skip > 1) |
Bcopy(rn_ones + 1, addmask_key + 1, skip - 1); |
if ((m0 = mlen) > skip) |
Bcopy(netmask + skip, addmask_key + skip, mlen - skip); |
/* |
* Trim trailing zeroes. |
*/ |
for (cp = addmask_key + mlen; (cp > addmask_key) && cp[-1] == 0;) |
cp--; |
mlen = cp - addmask_key; |
if (mlen <= skip) { |
if (m0 >= last_zeroed) |
last_zeroed = mlen; |
return (mask_rnhead->rnh_nodes); |
} |
if (m0 < last_zeroed) |
Bzero(addmask_key + m0, last_zeroed - m0); |
*addmask_key = last_zeroed = mlen; |
x = rn_search(addmask_key, rn_masktop); |
if (Bcmp(addmask_key, x->rn_key, mlen) != 0) |
x = 0; |
if (x || search) |
return (x); |
R_Malloc(x, struct radix_node *, max_keylen + 2 * sizeof (*x)); |
if ((saved_x = x) == 0) |
return (0); |
Bzero(x, max_keylen + 2 * sizeof (*x)); |
netmask = cp = (caddr_t)(x + 2); |
Bcopy(addmask_key, cp, mlen); |
x = rn_insert(cp, mask_rnhead, &maskduplicated, x); |
if (maskduplicated) { |
log(LOG_ERR, "rn_addmask: mask impossibly already in tree"); |
Free(saved_x); |
return (x); |
} |
/* |
* Calculate index of mask, and check for normalcy. |
*/ |
cplim = netmask + mlen; isnormal = 1; |
for (cp = netmask + skip; (cp < cplim) && *(u_char *)cp == 0xff;) |
cp++; |
if (cp != cplim) { |
for (j = 0x80; (j & *cp) != 0; j >>= 1) |
b++; |
if (*cp != normal_chars[b] || cp != (cplim - 1)) |
isnormal = 0; |
} |
b += (cp - netmask) << 3; |
x->rn_b = -1 - b; |
if (isnormal) |
x->rn_flags |= RNF_NORMAL; |
return (x); |
} |
|
static int /* XXX: arbitrary ordering for non-contiguous masks */ |
rn_lexobetter(m_arg, n_arg) |
void *m_arg, *n_arg; |
{ |
register u_char *mp = m_arg, *np = n_arg, *lim; |
|
if (*mp > *np) |
return 1; /* not really, but need to check longer one first */ |
if (*mp == *np) |
for (lim = mp + *mp; mp < lim;) |
if (*mp++ > *np++) |
return 1; |
return 0; |
} |
|
static struct radix_mask * |
rn_new_radix_mask(tt, next) |
register struct radix_node *tt; |
register struct radix_mask *next; |
{ |
register struct radix_mask *m; |
|
MKGet(m); |
if (m == 0) { |
log(LOG_ERR, "Mask for route not entered\n"); |
return (0); |
} |
Bzero(m, sizeof *m); |
m->rm_b = tt->rn_b; |
m->rm_flags = tt->rn_flags; |
if (tt->rn_flags & RNF_NORMAL) |
m->rm_leaf = tt; |
else |
m->rm_mask = tt->rn_mask; |
m->rm_mklist = next; |
tt->rn_mklist = m; |
return m; |
} |
|
struct radix_node * |
rn_addroute(v_arg, n_arg, head, treenodes) |
void *v_arg, *n_arg; |
struct radix_node_head *head; |
struct radix_node treenodes[2]; |
{ |
caddr_t v = (caddr_t)v_arg, netmask = (caddr_t)n_arg; |
register struct radix_node *t, *x = 0, *tt; |
struct radix_node *saved_tt, *top = head->rnh_treetop; |
short b = 0, b_leaf = 0; |
int keyduplicated; |
caddr_t mmask; |
struct radix_mask *m, **mp; |
|
/* |
* In dealing with non-contiguous masks, there may be |
* many different routes which have the same mask. |
* We will find it useful to have a unique pointer to |
* the mask to speed avoiding duplicate references at |
* nodes and possibly save time in calculating indices. |
*/ |
if (netmask) { |
if ((x = rn_addmask(netmask, 0, top->rn_off)) == 0) |
return (0); |
b_leaf = x->rn_b; |
b = -1 - x->rn_b; |
netmask = x->rn_key; |
} |
/* |
* Deal with duplicated keys: attach node to previous instance |
*/ |
saved_tt = tt = rn_insert(v, head, &keyduplicated, treenodes); |
if (keyduplicated) { |
for (t = tt; tt; t = tt, tt = tt->rn_dupedkey) { |
if (tt->rn_mask == netmask) |
return (0); |
if (netmask == 0 || |
(tt->rn_mask && |
((b_leaf < tt->rn_b) || /* index(netmask) > node */ |
rn_refines(netmask, tt->rn_mask) || |
rn_lexobetter(netmask, tt->rn_mask)))) |
break; |
} |
/* |
* If the mask is not duplicated, we wouldn't |
* find it among possible duplicate key entries |
* anyway, so the above test doesn't hurt. |
* |
* We sort the masks for a duplicated key the same way as |
* in a masklist -- most specific to least specific. |
* This may require the unfortunate nuisance of relocating |
* the head of the list. |
*/ |
if (tt == saved_tt) { |
struct radix_node *xx = x; |
/* link in at head of list */ |
(tt = treenodes)->rn_dupedkey = t; |
tt->rn_flags = t->rn_flags; |
tt->rn_p = x = t->rn_p; |
t->rn_p = tt; /* parent */ |
if (x->rn_l == t) x->rn_l = tt; else x->rn_r = tt; |
saved_tt = tt; x = xx; |
} else { |
(tt = treenodes)->rn_dupedkey = t->rn_dupedkey; |
t->rn_dupedkey = tt; |
tt->rn_p = t; /* parent */ |
if (tt->rn_dupedkey) /* parent */ |
tt->rn_dupedkey->rn_p = tt; /* parent */ |
} |
#ifdef RN_DEBUG |
t=tt+1; tt->rn_info = rn_nodenum++; t->rn_info = rn_nodenum++; |
tt->rn_twin = t; tt->rn_ybro = rn_clist; rn_clist = tt; |
#endif |
tt->rn_key = (caddr_t) v; |
tt->rn_b = -1; |
tt->rn_flags = RNF_ACTIVE; |
} |
/* |
* Put mask in tree. |
*/ |
if (netmask) { |
tt->rn_mask = netmask; |
tt->rn_b = x->rn_b; |
tt->rn_flags |= x->rn_flags & RNF_NORMAL; |
} |
t = saved_tt->rn_p; |
if (keyduplicated) |
goto on2; |
b_leaf = -1 - t->rn_b; |
if (t->rn_r == saved_tt) x = t->rn_l; else x = t->rn_r; |
/* Promote general routes from below */ |
if (x->rn_b < 0) { |
for (mp = &t->rn_mklist; x; x = x->rn_dupedkey) |
if (x->rn_mask && (x->rn_b >= b_leaf) && x->rn_mklist == 0) { |
*mp = m = rn_new_radix_mask(x, 0); |
if (m) |
mp = &m->rm_mklist; |
} |
} else if (x->rn_mklist) { |
/* |
* Skip over masks whose index is > that of new node |
*/ |
for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist) |
if (m->rm_b >= b_leaf) |
break; |
t->rn_mklist = m; *mp = 0; |
} |
on2: |
/* Add new route to highest possible ancestor's list */ |
if ((netmask == 0) || (b > t->rn_b )) |
return tt; /* can't lift at all */ |
b_leaf = tt->rn_b; |
do { |
x = t; |
t = t->rn_p; |
} while (b <= t->rn_b && x != top); |
/* |
* Search through routes associated with node to |
* insert new route according to index. |
* Need same criteria as when sorting dupedkeys to avoid |
* double loop on deletion. |
*/ |
for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist) { |
if (m->rm_b < b_leaf) |
continue; |
if (m->rm_b > b_leaf) |
break; |
if (m->rm_flags & RNF_NORMAL) { |
mmask = m->rm_leaf->rn_mask; |
if (tt->rn_flags & RNF_NORMAL) { |
log(LOG_ERR, |
"Non-unique normal route, mask not entered"); |
return tt; |
} |
} else |
mmask = m->rm_mask; |
if (mmask == netmask) { |
m->rm_refs++; |
tt->rn_mklist = m; |
return tt; |
} |
if (rn_refines(netmask, mmask) || rn_lexobetter(netmask, mmask)) |
break; |
} |
*mp = rn_new_radix_mask(tt, *mp); |
return tt; |
} |
|
static struct radix_node * |
rn_delete(v_arg, netmask_arg, head) |
void *v_arg, *netmask_arg; |
struct radix_node_head *head; |
{ |
register struct radix_node *t, *p, *x, *tt; |
struct radix_mask *m, *saved_m, **mp; |
struct radix_node *dupedkey, *saved_tt, *top; |
caddr_t v, netmask; |
int b, head_off, vlen; |
|
v = v_arg; |
netmask = netmask_arg; |
x = head->rnh_treetop; |
tt = rn_search(v, x); |
head_off = x->rn_off; |
vlen = *(u_char *)v; |
saved_tt = tt; |
top = x; |
if (tt == 0 || |
Bcmp(v + head_off, tt->rn_key + head_off, vlen - head_off)) |
return (0); |
/* |
* Delete our route from mask lists. |
*/ |
if (netmask) { |
if ((x = rn_addmask(netmask, 1, head_off)) == 0) |
return (0); |
netmask = x->rn_key; |
while (tt->rn_mask != netmask) |
if ((tt = tt->rn_dupedkey) == 0) |
return (0); |
} |
if (tt->rn_mask == 0 || (saved_m = m = tt->rn_mklist) == 0) |
goto on1; |
if (tt->rn_flags & RNF_NORMAL) { |
if (m->rm_leaf != tt || m->rm_refs > 0) { |
log(LOG_ERR, "rn_delete: inconsistent annotation\n"); |
return 0; /* dangling ref could cause disaster */ |
} |
} else { |
if (m->rm_mask != tt->rn_mask) { |
log(LOG_ERR, "rn_delete: inconsistent annotation\n"); |
goto on1; |
} |
if (--m->rm_refs >= 0) |
goto on1; |
} |
b = -1 - tt->rn_b; |
t = saved_tt->rn_p; |
if (b > t->rn_b) |
goto on1; /* Wasn't lifted at all */ |
do { |
x = t; |
t = t->rn_p; |
} while (b <= t->rn_b && x != top); |
for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist) |
if (m == saved_m) { |
*mp = m->rm_mklist; |
MKFree(m); |
break; |
} |
if (m == 0) { |
log(LOG_ERR, "rn_delete: couldn't find our annotation\n"); |
if (tt->rn_flags & RNF_NORMAL) |
return (0); /* Dangling ref to us */ |
} |
on1: |
/* |
* Eliminate us from tree |
*/ |
if (tt->rn_flags & RNF_ROOT) |
return (0); |
#ifdef RN_DEBUG |
/* Get us out of the creation list */ |
for (t = rn_clist; t && t->rn_ybro != tt; t = t->rn_ybro) {} |
if (t) t->rn_ybro = tt->rn_ybro; |
#endif |
t = tt->rn_p; |
dupedkey = saved_tt->rn_dupedkey; |
if (dupedkey) { |
/* |
* at this point, tt is the deletion target and saved_tt |
* is the head of the dupekey chain |
*/ |
if (tt == saved_tt) { |
/* remove from head of chain */ |
x = dupedkey; x->rn_p = t; |
if (t->rn_l == tt) t->rn_l = x; else t->rn_r = x; |
} else { |
/* find node in front of tt on the chain */ |
for (x = p = saved_tt; p && p->rn_dupedkey != tt;) |
p = p->rn_dupedkey; |
if (p) { |
p->rn_dupedkey = tt->rn_dupedkey; |
if (tt->rn_dupedkey) /* parent */ |
tt->rn_dupedkey->rn_p = p; /* parent */ |
} else log(LOG_ERR, "rn_delete: couldn't find us\n"); |
} |
t = tt + 1; |
if (t->rn_flags & RNF_ACTIVE) { |
#ifndef RN_DEBUG |
*++x = *t; p = t->rn_p; |
#else |
b = t->rn_info; *++x = *t; t->rn_info = b; p = t->rn_p; |
#endif |
if (p->rn_l == t) p->rn_l = x; else p->rn_r = x; |
x->rn_l->rn_p = x; x->rn_r->rn_p = x; |
} |
goto out; |
} |
if (t->rn_l == tt) x = t->rn_r; else x = t->rn_l; |
p = t->rn_p; |
if (p->rn_r == t) p->rn_r = x; else p->rn_l = x; |
x->rn_p = p; |
/* |
* Demote routes attached to us. |
*/ |
if (t->rn_mklist) { |
if (x->rn_b >= 0) { |
for (mp = &x->rn_mklist; (m = *mp);) |
mp = &m->rm_mklist; |
*mp = t->rn_mklist; |
} else { |
/* If there are any key,mask pairs in a sibling |
duped-key chain, some subset will appear sorted |
in the same order attached to our mklist */ |
for (m = t->rn_mklist; m && x; x = x->rn_dupedkey) |
if (m == x->rn_mklist) { |
struct radix_mask *mm = m->rm_mklist; |
x->rn_mklist = 0; |
if (--(m->rm_refs) < 0) |
MKFree(m); |
m = mm; |
} |
if (m) |
log(LOG_ERR, "%s %p at %x\n", |
"rn_delete: Orphaned Mask", m, x); |
} |
} |
/* |
* We may be holding an active internal node in the tree. |
*/ |
x = tt + 1; |
if (t != x) { |
#ifndef RN_DEBUG |
*t = *x; |
#else |
b = t->rn_info; *t = *x; t->rn_info = b; |
#endif |
t->rn_l->rn_p = t; t->rn_r->rn_p = t; |
p = x->rn_p; |
if (p->rn_l == x) p->rn_l = t; else p->rn_r = t; |
} |
out: |
tt->rn_flags &= ~RNF_ACTIVE; |
tt[1].rn_flags &= ~RNF_ACTIVE; |
return (tt); |
} |
|
/* |
* This is the same as rn_walktree() except for the parameters and the |
* exit. |
*/ |
static int |
rn_walktree_from(h, a, m, f, w) |
struct radix_node_head *h; |
void *a, *m; |
walktree_f_t *f; |
void *w; |
{ |
int error; |
struct radix_node *base, *next; |
u_char *xa = (u_char *)a; |
u_char *xm = (u_char *)m; |
register struct radix_node *rn, *last = 0 /* shut up gcc */; |
int stopping = 0; |
int lastb; |
|
/* |
* rn_search_m is sort-of-open-coded here. |
*/ |
/* printf("about to search\n"); */ |
for (rn = h->rnh_treetop; rn->rn_b >= 0; ) { |
last = rn; |
/* printf("rn_b %d, rn_bmask %x, xm[rn_off] %x\n", |
rn->rn_b, rn->rn_bmask, xm[rn->rn_off]); */ |
if (!(rn->rn_bmask & xm[rn->rn_off])) { |
break; |
} |
if (rn->rn_bmask & xa[rn->rn_off]) { |
rn = rn->rn_r; |
} else { |
rn = rn->rn_l; |
} |
} |
/* printf("done searching\n"); */ |
|
/* |
* Two cases: either we stepped off the end of our mask, |
* in which case last == rn, or we reached a leaf, in which |
* case we want to start from the last node we looked at. |
* Either way, last is the node we want to start from. |
*/ |
rn = last; |
lastb = rn->rn_b; |
|
/* printf("rn %p, lastb %d\n", rn, lastb);*/ |
|
/* |
* This gets complicated because we may delete the node |
* while applying the function f to it, so we need to calculate |
* the successor node in advance. |
*/ |
while (rn->rn_b >= 0) |
rn = rn->rn_l; |
|
while (!stopping) { |
/* printf("node %p (%d)\n", rn, rn->rn_b); */ |
base = rn; |
/* If at right child go back up, otherwise, go right */ |
while (rn->rn_p->rn_r == rn && !(rn->rn_flags & RNF_ROOT)) { |
rn = rn->rn_p; |
|
/* if went up beyond last, stop */ |
if (rn->rn_b < lastb) { |
stopping = 1; |
/* printf("up too far\n"); */ |
} |
} |
|
/* Find the next *leaf* since next node might vanish, too */ |
for (rn = rn->rn_p->rn_r; rn->rn_b >= 0;) |
rn = rn->rn_l; |
next = rn; |
/* Process leaves */ |
while ((rn = base) != 0) { |
base = rn->rn_dupedkey; |
/* printf("leaf %p\n", rn); */ |
if (!(rn->rn_flags & RNF_ROOT) |
&& (error = (*f)(rn, w))) |
return (error); |
} |
rn = next; |
|
if (rn->rn_flags & RNF_ROOT) { |
/* printf("root, stopping"); */ |
stopping = 1; |
} |
|
} |
return 0; |
} |
|
static int |
rn_walktree(h, f, w) |
struct radix_node_head *h; |
walktree_f_t *f; |
void *w; |
{ |
int error; |
struct radix_node *base, *next; |
register struct radix_node *rn = h->rnh_treetop; |
/* |
* This gets complicated because we may delete the node |
* while applying the function f to it, so we need to calculate |
* the successor node in advance. |
*/ |
/* First time through node, go left */ |
while (rn->rn_b >= 0) |
rn = rn->rn_l; |
for (;;) { |
base = rn; |
/* If at right child go back up, otherwise, go right */ |
while (rn->rn_p->rn_r == rn && (rn->rn_flags & RNF_ROOT) == 0) |
rn = rn->rn_p; |
/* Find the next *leaf* since next node might vanish, too */ |
for (rn = rn->rn_p->rn_r; rn->rn_b >= 0;) |
rn = rn->rn_l; |
next = rn; |
/* Process leaves */ |
while ((rn = base)) { |
base = rn->rn_dupedkey; |
if (!(rn->rn_flags & RNF_ROOT) && (error = (*f)(rn, w))) |
return (error); |
} |
rn = next; |
if (rn->rn_flags & RNF_ROOT) |
return (0); |
} |
/* NOTREACHED */ |
} |
|
int |
rn_inithead(head, off) |
void **head; |
int off; |
{ |
register struct radix_node_head *rnh; |
register struct radix_node *t, *tt, *ttt; |
if (*head) |
return (1); |
R_Malloc(rnh, struct radix_node_head *, sizeof (*rnh)); |
if (rnh == 0) |
return (0); |
Bzero(rnh, sizeof (*rnh)); |
*head = rnh; |
t = rn_newpair(rn_zeros, off, rnh->rnh_nodes); |
ttt = rnh->rnh_nodes + 2; |
t->rn_r = ttt; |
t->rn_p = t; |
tt = t->rn_l; |
tt->rn_flags = t->rn_flags = RNF_ROOT | RNF_ACTIVE; |
tt->rn_b = -1 - off; |
*ttt = *tt; |
ttt->rn_key = rn_ones; |
rnh->rnh_addaddr = rn_addroute; |
rnh->rnh_deladdr = rn_delete; |
rnh->rnh_matchaddr = rn_match; |
rnh->rnh_lookup = rn_lookup; |
rnh->rnh_walktree = rn_walktree; |
rnh->rnh_walktree_from = rn_walktree_from; |
rnh->rnh_treetop = t; |
return (1); |
} |
|
void |
rn_init() |
{ |
char *cp, *cplim; |
#ifdef KERNEL |
struct domain *dom; |
|
for (dom = domains; dom; dom = dom->dom_next) |
if (dom->dom_maxrtkey > max_keylen) |
max_keylen = dom->dom_maxrtkey; |
#endif |
if (max_keylen == 0) { |
log(LOG_ERR, |
"rn_init: radix functions require max_keylen be set\n"); |
return; |
} |
R_Malloc(rn_zeros, char *, 3 * max_keylen); |
if (rn_zeros == NULL) |
panic("rn_init"); |
Bzero(rn_zeros, 3 * max_keylen); |
rn_ones = cp = rn_zeros + max_keylen; |
addmask_key = cplim = rn_ones + max_keylen; |
while (cp < cplim) |
*cp++ = -1; |
if (rn_inithead((void **)&mask_rnhead, 0) == 0) |
panic("rn_init 2"); |
} |
/netisr.h
0,0 → 1,90
/* |
* Copyright (c) 1980, 1986, 1989, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)netisr.h 8.1 (Berkeley) 6/10/93 |
* $Id: netisr.h,v 1.2 2001-09-27 12:01:54 chris Exp $ |
*/ |
|
#ifndef _NET_NETISR_H_ |
#define _NET_NETISR_H_ |
|
/* |
* The networking code runs off software interrupts. |
* |
* You can switch into the network by doing splnet() and return by splx(). |
* The software interrupt level for the network is higher than the software |
* level for the clock (so you can enter the network in routines called |
* at timeout time). |
*/ |
#if defined(vax) || defined(tahoe) |
#define setsoftnet() mtpr(SIRR, 12) |
#endif |
|
/* |
* Each ``pup-level-1'' input queue has a bit in a ``netisr'' status |
* word which is used to de-multiplex a single software |
* interrupt used for scheduling the network code to calls |
* on the lowest level routine of each protocol. |
*/ |
#define NETISR_RAW 0 /* same as AF_UNSPEC */ |
#define NETISR_IP 2 /* same as AF_INET */ |
#define NETISR_IMP 3 /* same as AF_IMPLINK */ |
#define NETISR_NS 6 /* same as AF_NS */ |
#define NETISR_ISO 7 /* same as AF_ISO */ |
#define NETISR_CCITT 10 /* same as AF_CCITT */ |
#define NETISR_ATALK 16 /* same as AF_APPLETALK */ |
#define NETISR_ARP 18 /* same as AF_LINK */ |
#define NETISR_IPX 23 /* same as AF_IPX */ |
#define NETISR_ISDN 26 /* same as AF_E164 */ |
#define NETISR_PPP 27 /* PPP soft interrupt */ |
|
#define schednetisr(anisr) rtems_bsdnet_schednetisr(anisr) |
|
#ifndef LOCORE |
#ifdef KERNEL |
extern volatile unsigned int netisr; /* scheduling bits for network */ |
|
typedef void netisr_t(void); |
|
struct netisrtab { |
int nit_num; |
netisr_t *nit_isr; |
}; |
|
#define NETISR_SET(num, isr) |
|
int register_netisr __P((int, netisr_t *)); |
|
#endif |
#endif |
|
#endif |
/radix.h
0,0 → 1,165
/* |
* Copyright (c) 1988, 1989, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)radix.h 8.2 (Berkeley) 10/31/94 |
* $Id: radix.h,v 1.2 2001-09-27 12:01:54 chris Exp $ |
*/ |
|
#ifndef _RADIX_H_ |
#define _RADIX_H_ |
|
/* |
* Radix search tree node layout. |
*/ |
|
struct radix_node { |
struct radix_mask *rn_mklist; /* list of masks contained in subtree */ |
struct radix_node *rn_p; /* parent */ |
short rn_b; /* bit offset; -1-index(netmask) */ |
char rn_bmask; /* node: mask for bit test*/ |
u_char rn_flags; /* enumerated next */ |
#define RNF_NORMAL 1 /* leaf contains normal route */ |
#define RNF_ROOT 2 /* leaf is root leaf for tree */ |
#define RNF_ACTIVE 4 /* This node is alive (for rtfree) */ |
union { |
struct { /* leaf only data: */ |
caddr_t rn_Key; /* object of search */ |
caddr_t rn_Mask; /* netmask, if present */ |
struct radix_node *rn_Dupedkey; |
} rn_leaf; |
struct { /* node only data: */ |
int rn_Off; /* where to start compare */ |
struct radix_node *rn_L;/* progeny */ |
struct radix_node *rn_R;/* progeny */ |
} rn_node; |
} rn_u; |
#ifdef RN_DEBUG |
int rn_info; |
struct radix_node *rn_twin; |
struct radix_node *rn_ybro; |
#endif |
}; |
|
#define rn_dupedkey rn_u.rn_leaf.rn_Dupedkey |
#define rn_key rn_u.rn_leaf.rn_Key |
#define rn_mask rn_u.rn_leaf.rn_Mask |
#define rn_off rn_u.rn_node.rn_Off |
#define rn_l rn_u.rn_node.rn_L |
#define rn_r rn_u.rn_node.rn_R |
|
/* |
* Annotations to tree concerning potential routes applying to subtrees. |
*/ |
|
extern struct radix_mask { |
short rm_b; /* bit offset; -1-index(netmask) */ |
char rm_unused; /* cf. rn_bmask */ |
u_char rm_flags; /* cf. rn_flags */ |
struct radix_mask *rm_mklist; /* more masks to try */ |
union { |
caddr_t rmu_mask; /* the mask */ |
struct radix_node *rmu_leaf; /* for normal routes */ |
} rm_rmu; |
int rm_refs; /* # of references to this struct */ |
} *rn_mkfreelist; |
|
#define rm_mask rm_rmu.rmu_mask |
#define rm_leaf rm_rmu.rmu_leaf /* extra field would make 32 bytes */ |
|
#define MKGet(m) {\ |
if (rn_mkfreelist) {\ |
m = rn_mkfreelist; \ |
rn_mkfreelist = (m)->rm_mklist; \ |
} else \ |
R_Malloc(m, struct radix_mask *, sizeof (*(m))); }\ |
|
#define MKFree(m) { (m)->rm_mklist = rn_mkfreelist; rn_mkfreelist = (m);} |
|
typedef int walktree_f_t __P((struct radix_node *, void *)); |
|
struct radix_node_head { |
struct radix_node *rnh_treetop; |
int rnh_addrsize; /* permit, but not require fixed keys */ |
int rnh_pktsize; /* permit, but not require fixed keys */ |
struct radix_node *(*rnh_addaddr) /* add based on sockaddr */ |
__P((void *v, void *mask, |
struct radix_node_head *head, struct radix_node nodes[])); |
struct radix_node *(*rnh_addpkt) /* add based on packet hdr */ |
__P((void *v, void *mask, |
struct radix_node_head *head, struct radix_node nodes[])); |
struct radix_node *(*rnh_deladdr) /* remove based on sockaddr */ |
__P((void *v, void *mask, struct radix_node_head *head)); |
struct radix_node *(*rnh_delpkt) /* remove based on packet hdr */ |
__P((void *v, void *mask, struct radix_node_head *head)); |
struct radix_node *(*rnh_matchaddr) /* locate based on sockaddr */ |
__P((void *v, struct radix_node_head *head)); |
struct radix_node *(*rnh_lookup) /* locate based on sockaddr */ |
__P((void *v, void *mask, struct radix_node_head *head)); |
struct radix_node *(*rnh_matchpkt) /* locate based on packet hdr */ |
__P((void *v, struct radix_node_head *head)); |
int (*rnh_walktree) /* traverse tree */ |
__P((struct radix_node_head *head, walktree_f_t *f, void *w)); |
int (*rnh_walktree_from) /* traverse tree below a */ |
__P((struct radix_node_head *head, void *a, void *m, |
walktree_f_t *f, void *w)); |
void (*rnh_close) /* do something when the last ref drops */ |
__P((struct radix_node *rn, struct radix_node_head *head)); |
struct radix_node rnh_nodes[3]; /* empty tree for common case */ |
}; |
|
#ifndef KERNEL |
#define Bcmp(a, b, n) bcmp(((char *)(a)), ((char *)(b)), (n)) |
#define Bcopy(a, b, n) bcopy(((char *)(a)), ((char *)(b)), (unsigned)(n)) |
#define Bzero(p, n) bzero((char *)(p), (int)(n)); |
#define R_Malloc(p, t, n) (p = (t) malloc((unsigned int)(n))) |
#define Free(p) free((char *)p); |
#else |
#define Bcmp(a, b, n) bcmp(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n)) |
#define Bcopy(a, b, n) bcopy(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n)) |
#define Bzero(p, n) bzero((caddr_t)(p), (unsigned)(n)); |
#define R_Malloc(p, t, n) (p = (t) malloc((unsigned long)(n), M_RTABLE, M_DONTWAIT)) |
#define Free(p) free((caddr_t)p, M_RTABLE); |
#endif /*KERNEL*/ |
|
extern struct radix_node_head *mask_rnhead; |
|
void rn_init __P((void)); |
int rn_inithead __P((void **, int)); |
int rn_refines __P((void *, void *)); |
struct radix_node |
*rn_addmask __P((void *, int, int)), |
*rn_addroute __P((void *, void *, struct radix_node_head *, |
struct radix_node [2])), |
*rn_match __P((void *, struct radix_node_head *)); |
|
|
#endif /* _RADIX_H_ */ |
/bpf.h
0,0 → 1,236
/* |
* Copyright (c) 1990, 1991, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* This code is derived from the Stanford/CMU enet packet filter, |
* (net/enet.c) distributed as part of 4.3BSD, and code contributed |
* to Berkeley by Steven McCanne and Van Jacobson both of Lawrence |
* Berkeley Laboratory. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)bpf.h 8.1 (Berkeley) 6/10/93 |
* @(#)bpf.h 1.34 (LBL) 6/16/96 |
* |
* $Id: bpf.h,v 1.2 2001-09-27 12:01:54 chris Exp $ |
*/ |
|
#ifndef _NET_BPF_H_ |
#define _NET_BPF_H_ |
|
/* BSD style release date */ |
#define BPF_RELEASE 199606 |
|
typedef int32_t bpf_int32; |
typedef u_int32_t bpf_u_int32; |
|
/* |
* Alignment macros. BPF_WORDALIGN rounds up to the next |
* even multiple of BPF_ALIGNMENT. |
*/ |
#define BPF_ALIGNMENT sizeof(bpf_int32) |
#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1)) |
|
#define BPF_MAXINSNS 512 |
#define BPF_MAXBUFSIZE 0x8000 |
#define BPF_MINBUFSIZE 32 |
|
/* |
* Structure for BIOCSETF. |
*/ |
struct bpf_program { |
u_int bf_len; |
struct bpf_insn *bf_insns; |
}; |
|
/* |
* Struct returned by BIOCGSTATS. |
*/ |
struct bpf_stat { |
u_int bs_recv; /* number of packets received */ |
u_int bs_drop; /* number of packets dropped */ |
}; |
|
/* |
* Struct return by BIOCVERSION. This represents the version number of |
* the filter language described by the instruction encodings below. |
* bpf understands a program iff kernel_major == filter_major && |
* kernel_minor >= filter_minor, that is, if the value returned by the |
* running kernel has the same major number and a minor number equal |
* equal to or less than the filter being downloaded. Otherwise, the |
* results are undefined, meaning an error may be returned or packets |
* may be accepted haphazardly. |
* It has nothing to do with the source code version. |
*/ |
struct bpf_version { |
u_short bv_major; |
u_short bv_minor; |
}; |
/* Current version number of filter architecture. */ |
#define BPF_MAJOR_VERSION 1 |
#define BPF_MINOR_VERSION 1 |
|
#define BIOCGBLEN _IOR('B',102, u_int) |
#define BIOCSBLEN _IOWR('B',102, u_int) |
#define BIOCSETF _IOW('B',103, struct bpf_program) |
#define BIOCFLUSH _IO('B',104) |
#define BIOCPROMISC _IO('B',105) |
#define BIOCGDLT _IOR('B',106, u_int) |
#define BIOCGETIF _IOR('B',107, struct ifreq) |
#define BIOCSETIF _IOW('B',108, struct ifreq) |
#define BIOCSRTIMEOUT _IOW('B',109, struct timeval) |
#define BIOCGRTIMEOUT _IOR('B',110, struct timeval) |
#define BIOCGSTATS _IOR('B',111, struct bpf_stat) |
#define BIOCIMMEDIATE _IOW('B',112, u_int) |
#define BIOCVERSION _IOR('B',113, struct bpf_version) |
#define BIOCGRSIG _IOR('B',114, u_int) |
#define BIOCSRSIG _IOW('B',115, u_int) |
|
/* |
* Structure prepended to each packet. |
*/ |
struct bpf_hdr { |
struct timeval bh_tstamp; /* time stamp */ |
bpf_u_int32 bh_caplen; /* length of captured portion */ |
bpf_u_int32 bh_datalen; /* original length of packet */ |
u_short bh_hdrlen; /* length of bpf header (this struct |
plus alignment padding) */ |
}; |
/* |
* Because the structure above is not a multiple of 4 bytes, some compilers |
* will insist on inserting padding; hence, sizeof(struct bpf_hdr) won't work. |
* Only the kernel needs to know about it; applications use bh_hdrlen. |
*/ |
#ifdef KERNEL |
#define SIZEOF_BPF_HDR 18 |
#endif |
|
/* |
* Data-link level type codes. |
*/ |
#define DLT_NULL 0 /* no link-layer encapsulation */ |
#define DLT_EN10MB 1 /* Ethernet (10Mb) */ |
#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */ |
#define DLT_AX25 3 /* Amateur Radio AX.25 */ |
#define DLT_PRONET 4 /* Proteon ProNET Token Ring */ |
#define DLT_CHAOS 5 /* Chaos */ |
#define DLT_IEEE802 6 /* IEEE 802 Networks */ |
#define DLT_ARCNET 7 /* ARCNET */ |
#define DLT_SLIP 8 /* Serial Line IP */ |
#define DLT_PPP 9 /* Point-to-point Protocol */ |
#define DLT_FDDI 10 /* FDDI */ |
#define DLT_ATM_RFC1483 11 /* LLC/SNAP encapsulated atm */ |
|
/* |
* The instruction encodings. |
*/ |
/* instruction classes */ |
#define BPF_CLASS(code) ((code) & 0x07) |
#define BPF_LD 0x00 |
#define BPF_LDX 0x01 |
#define BPF_ST 0x02 |
#define BPF_STX 0x03 |
#define BPF_ALU 0x04 |
#define BPF_JMP 0x05 |
#define BPF_RET 0x06 |
#define BPF_MISC 0x07 |
|
/* ld/ldx fields */ |
#define BPF_SIZE(code) ((code) & 0x18) |
#define BPF_W 0x00 |
#define BPF_H 0x08 |
#define BPF_B 0x10 |
#define BPF_MODE(code) ((code) & 0xe0) |
#define BPF_IMM 0x00 |
#define BPF_ABS 0x20 |
#define BPF_IND 0x40 |
#define BPF_MEM 0x60 |
#define BPF_LEN 0x80 |
#define BPF_MSH 0xa0 |
|
/* alu/jmp fields */ |
#define BPF_OP(code) ((code) & 0xf0) |
#define BPF_ADD 0x00 |
#define BPF_SUB 0x10 |
#define BPF_MUL 0x20 |
#define BPF_DIV 0x30 |
#define BPF_OR 0x40 |
#define BPF_AND 0x50 |
#define BPF_LSH 0x60 |
#define BPF_RSH 0x70 |
#define BPF_NEG 0x80 |
#define BPF_JA 0x00 |
#define BPF_JEQ 0x10 |
#define BPF_JGT 0x20 |
#define BPF_JGE 0x30 |
#define BPF_JSET 0x40 |
#define BPF_SRC(code) ((code) & 0x08) |
#define BPF_K 0x00 |
#define BPF_X 0x08 |
|
/* ret - BPF_K and BPF_X also apply */ |
#define BPF_RVAL(code) ((code) & 0x18) |
#define BPF_A 0x10 |
|
/* misc */ |
#define BPF_MISCOP(code) ((code) & 0xf8) |
#define BPF_TAX 0x00 |
#define BPF_TXA 0x80 |
|
/* |
* The instruction data structure. |
*/ |
struct bpf_insn { |
u_short code; |
u_char jt; |
u_char jf; |
bpf_u_int32 k; |
}; |
|
/* |
* Macros for insn array initializers. |
*/ |
#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k } |
#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k } |
|
#ifdef KERNEL |
int bpf_validate __P((struct bpf_insn *, int)); |
void bpf_tap __P((struct ifnet *, u_char *, u_int)); |
void bpf_mtap __P((struct ifnet *, struct mbuf *)); |
void bpfattach __P((struct ifnet *, u_int, u_int)); |
void bpfilterattach __P((int)); |
u_int bpf_filter __P((struct bpf_insn *, u_char *, u_int, u_int)); |
#endif |
|
/* |
* Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST). |
*/ |
#define BPF_MEMWORDS 16 |
|
#endif |
/if_ethersubr.c
0,0 → 1,997
/* |
* Copyright (c) 1982, 1989, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93 |
* $Id: if_ethersubr.c,v 1.2 2001-09-27 12:01:54 chris Exp $ |
*/ |
|
#include <sys/param.h> |
#include <sys/systm.h> |
#include <sys/kernel.h> |
#include <sys/malloc.h> |
#include <sys/mbuf.h> |
#include <sys/protosw.h> |
#include <sys/socket.h> |
#include <sys/ioctl.h> |
#include <sys/errno.h> |
#include <sys/syslog.h> |
#include <sys/sysctl.h> |
|
#include <net/if.h> |
#include <net/netisr.h> |
#include <net/route.h> |
#include <net/if_llc.h> |
#include <net/if_dl.h> |
#include <net/if_types.h> |
#include <net/ethernet.h> |
|
#ifdef INET |
#include <netinet/in.h> |
#include <netinet/in_var.h> |
#endif |
#include <netinet/if_ether.h> |
|
#ifdef IPX |
#include <netipx/ipx.h> |
#include <netipx/ipx_if.h> |
#endif |
|
#ifdef NS |
#include <netns/ns.h> |
#include <netns/ns_if.h> |
ushort ns_nettype; |
int ether_outputdebug = 0; |
int ether_inputdebug = 0; |
#endif |
|
#ifdef ISO |
#include <netiso/argo_debug.h> |
#include <netiso/iso.h> |
#include <netiso/iso_var.h> |
#include <netiso/iso_snpac.h> |
#endif |
|
/*#ifdef LLC |
#include <netccitt/dll.h> |
#include <netccitt/llc_var.h> |
#endif*/ |
|
#if defined(LLC) && defined(CCITT) |
extern struct ifqueue pkintrq; |
#endif |
|
#ifdef NETATALK |
#include <netatalk/at.h> |
#include <netatalk/at_var.h> |
#include <netatalk/at_extern.h> |
|
#define llc_snap_org_code llc_un.type_snap.org_code |
#define llc_snap_ether_type llc_un.type_snap.ether_type |
|
extern u_char at_org_code[ 3 ]; |
extern u_char aarp_org_code[ 3 ]; |
#endif NETATALK |
|
u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; |
#define senderr(e) { error = (e); goto bad;} |
|
/* |
* Ethernet output routine. |
* Encapsulate a packet of type family for the local net. |
* Use trailer local net encapsulation if enough data in first |
* packet leaves a multiple of 512 bytes of data in remainder. |
* Assumes that ifp is actually pointer to arpcom structure. |
*/ |
int |
ether_output(ifp, m0, dst, rt0) |
register struct ifnet *ifp; |
struct mbuf *m0; |
struct sockaddr *dst; |
struct rtentry *rt0; |
{ |
short type; |
int s, error = 0; |
#ifdef NS |
u_char *cp |
register struct ifqueue *inq; |
register struct mbuf *m2; |
#endif |
u_char edst[6]; |
register struct mbuf *m = m0; |
register struct rtentry *rt; |
struct mbuf *mcopy = (struct mbuf *)0; |
register struct ether_header *eh; |
int off, len = m->m_pkthdr.len; |
struct arpcom *ac = (struct arpcom *)ifp; |
#ifdef NETATALK |
struct at_ifaddr *aa; |
#endif NETATALK |
|
if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) |
senderr(ENETDOWN); |
rt = rt0; |
if (rt) { |
if ((rt->rt_flags & RTF_UP) == 0) { |
rt0 = rt = rtalloc1(dst, 1, 0UL); |
if (rt0) |
rt->rt_refcnt--; |
else |
senderr(EHOSTUNREACH); |
} |
if (rt->rt_flags & RTF_GATEWAY) { |
if (rt->rt_gwroute == 0) |
goto lookup; |
if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { |
rtfree(rt); rt = rt0; |
lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1, |
0UL); |
if ((rt = rt->rt_gwroute) == 0) |
senderr(EHOSTUNREACH); |
} |
} |
if (rt->rt_flags & RTF_REJECT) |
if (rt->rt_rmx.rmx_expire == 0 || |
rtems_bsdnet_seconds_since_boot() < rt->rt_rmx.rmx_expire) |
senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); |
} |
switch (dst->sa_family) { |
|
#ifdef INET |
case AF_INET: |
if (!arpresolve(ac, rt, m, dst, edst, rt0)) |
return (0); /* if not yet resolved */ |
/* If broadcasting on a simplex interface, loopback a copy */ |
if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) |
mcopy = m_copy(m, 0, (int)M_COPYALL); |
off = m->m_pkthdr.len - m->m_len; |
type = htons(ETHERTYPE_IP); |
break; |
#endif |
#ifdef IPX |
case AF_IPX: |
{ |
struct ifaddr *ia; |
|
type = htons(ETHERTYPE_IPX); |
bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host), |
(caddr_t)edst, sizeof (edst)); |
for (ia = ifp->if_addrlist; ia != NULL; ia = ia->ifa_next) |
if(ia->ifa_addr->sa_family == AF_IPX && |
!bcmp((caddr_t)edst, |
(caddr_t)&((struct ipx_ifaddr *)ia)->ia_addr.sipx_addr.x_host, |
sizeof(edst))) |
return (looutput(ifp, m, dst, rt)); |
/* If broadcasting on a simplex interface, loopback a copy */ |
if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) |
mcopy = m_copy(m, 0, (int)M_COPYALL); |
break; |
} |
#endif |
#ifdef NETATALK |
case AF_APPLETALK: |
{ |
struct sockaddr_at *sat = (struct sockaddr_at *)dst; |
|
/* |
* super hack.. |
* Most of this loopback code should move into the appletalk |
* code, but it's here for now.. remember to move it! [JRE] |
* This may not get the same interface we started with |
* fix asap. XXX |
*/ |
aa = at_ifawithnet( sat ); |
if (aa == NULL) { |
goto bad; |
} |
if( aa->aa_ifa.ifa_ifp != ifp ) { |
(*aa->aa_ifa.ifa_ifp->if_output)(aa->aa_ifa.ifa_ifp, |
m,dst,rt); |
} |
if (((sat->sat_addr.s_net == ATADDR_ANYNET) |
&& (sat->sat_addr.s_node == ATADDR_ANYNODE)) |
|| ((sat->sat_addr.s_net == aa->aa_addr.sat_addr.s_net ) |
&& (sat->sat_addr.s_node == aa->aa_addr.sat_addr.s_node))) { |
(void) looutput(ifp, m, dst, rt); |
return(0); |
} |
|
if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst)) { |
#ifdef NETATALKDEBUG |
extern char *prsockaddr(struct sockaddr *); |
printf("aarpresolv: failed for %s\n", prsockaddr(dst)); |
#endif NETATALKDEBUG |
return (0); |
} |
|
/* |
* If broadcasting on a simplex interface, loopback a copy |
*/ |
if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) |
mcopy = m_copy(m, 0, (int)M_COPYALL); |
} |
/* |
* In the phase 2 case, we need to prepend an mbuf for the llc header. |
* Since we must preserve the value of m, which is passed to us by |
* value, we m_copy() the first mbuf, and use it for our llc header. |
*/ |
if ( aa->aa_flags & AFA_PHASE2 ) { |
struct llc llc; |
|
M_PREPEND(m, sizeof(struct llc), M_WAIT); |
len += sizeof(struct llc); |
llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP; |
llc.llc_control = LLC_UI; |
bcopy(at_org_code, llc.llc_snap_org_code, sizeof(at_org_code)); |
llc.llc_snap_ether_type = htons( ETHERTYPE_AT ); |
bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc)); |
type = htons(m->m_pkthdr.len); |
} else { |
type = htons(ETHERTYPE_AT); |
} |
break; |
#endif NETATALK |
#ifdef NS |
case AF_NS: |
switch(ns_nettype){ |
default: |
case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */ |
type = 0x8137; |
break; |
case 0x0: /* Novell 802.3 */ |
type = htons( m->m_pkthdr.len); |
break; |
case 0xe0e0: /* Novell 802.2 and Token-Ring */ |
M_PREPEND(m, 3, M_WAIT); |
type = htons( m->m_pkthdr.len); |
cp = mtod(m, u_char *); |
*cp++ = 0xE0; |
*cp++ = 0xE0; |
*cp++ = 0x03; |
break; |
} |
bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), |
(caddr_t)edst, sizeof (edst)); |
if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))){ |
m->m_pkthdr.rcvif = ifp; |
schednetisr(NETISR_NS); |
inq = &nsintrq; |
s = splimp(); |
if (IF_QFULL(inq)) { |
IF_DROP(inq); |
m_freem(m); |
} else |
IF_ENQUEUE(inq, m); |
splx(s); |
return (error); |
} |
if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, sizeof(edst))){ |
m2 = m_copy(m, 0, (int)M_COPYALL); |
m2->m_pkthdr.rcvif = ifp; |
schednetisr(NETISR_NS); |
inq = &nsintrq; |
s = splimp(); |
if (IF_QFULL(inq)) { |
IF_DROP(inq); |
m_freem(m2); |
} else |
IF_ENQUEUE(inq, m2); |
splx(s); |
} |
/* If broadcasting on a simplex interface, loopback a copy */ |
if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)){ |
mcopy = m_copy(m, 0, (int)M_COPYALL); |
} |
break; |
#endif /* NS */ |
#ifdef ISO |
case AF_ISO: { |
int snpalen; |
struct llc *l; |
register struct sockaddr_dl *sdl; |
|
if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) && |
sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) { |
bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst)); |
} else if (error = |
iso_snparesolve(ifp, (struct sockaddr_iso *)dst, |
(char *)edst, &snpalen)) |
goto bad; /* Not Resolved */ |
/* If broadcasting on a simplex interface, loopback a copy */ |
if (*edst & 1) |
m->m_flags |= (M_BCAST|M_MCAST); |
if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) && |
(mcopy = m_copy(m, 0, (int)M_COPYALL))) { |
M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT); |
if (mcopy) { |
eh = mtod(mcopy, struct ether_header *); |
bcopy((caddr_t)edst, |
(caddr_t)eh->ether_dhost, sizeof (edst)); |
bcopy((caddr_t)ac->ac_enaddr, |
(caddr_t)eh->ether_shost, sizeof (edst)); |
} |
} |
M_PREPEND(m, 3, M_DONTWAIT); |
if (m == NULL) |
return (0); |
type = htons(m->m_pkthdr.len); |
l = mtod(m, struct llc *); |
l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP; |
l->llc_control = LLC_UI; |
len += 3; |
IFDEBUG(D_ETHER) |
int i; |
printf("unoutput: sending pkt to: "); |
for (i=0; i<6; i++) |
printf("%x ", edst[i] & 0xff); |
printf("\n"); |
ENDDEBUG |
} break; |
#endif /* ISO */ |
#ifdef LLC |
/* case AF_NSAP: */ |
case AF_CCITT: { |
register struct sockaddr_dl *sdl = |
(struct sockaddr_dl *) rt -> rt_gateway; |
|
if (sdl && sdl->sdl_family == AF_LINK |
&& sdl->sdl_alen > 0) { |
bcopy(LLADDR(sdl), (char *)edst, |
sizeof(edst)); |
} else goto bad; /* Not a link interface ? Funny ... */ |
if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) && |
(mcopy = m_copy(m, 0, (int)M_COPYALL))) { |
M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT); |
if (mcopy) { |
eh = mtod(mcopy, struct ether_header *); |
bcopy((caddr_t)edst, |
(caddr_t)eh->ether_dhost, sizeof (edst)); |
bcopy((caddr_t)ac->ac_enaddr, |
(caddr_t)eh->ether_shost, sizeof (edst)); |
} |
} |
type = htons(m->m_pkthdr.len); |
#ifdef LLC_DEBUG |
{ |
int i; |
register struct llc *l = mtod(m, struct llc *); |
|
printf("ether_output: sending LLC2 pkt to: "); |
for (i=0; i<6; i++) |
printf("%x ", edst[i] & 0xff); |
printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n", |
type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff, |
l->llc_control & 0xff); |
|
} |
#endif /* LLC_DEBUG */ |
} break; |
#endif /* LLC */ |
|
case AF_UNSPEC: |
eh = (struct ether_header *)dst->sa_data; |
(void)memcpy(edst, eh->ether_dhost, sizeof (edst)); |
type = eh->ether_type; |
break; |
|
default: |
printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, |
dst->sa_family); |
senderr(EAFNOSUPPORT); |
} |
|
|
if (mcopy) |
(void) looutput(ifp, mcopy, dst, rt); |
/* |
* Add local net header. If no space in first mbuf, |
* allocate another. |
*/ |
M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT); |
if (m == 0) |
senderr(ENOBUFS); |
eh = mtod(m, struct ether_header *); |
(void)memcpy(&eh->ether_type, &type, |
sizeof(eh->ether_type)); |
(void)memcpy(eh->ether_dhost, edst, sizeof (edst)); |
(void)memcpy(eh->ether_shost, ac->ac_enaddr, |
sizeof(eh->ether_shost)); |
s = splimp(); |
/* |
* Queue message on interface, and start output if interface |
* not yet active. |
*/ |
if (IF_QFULL(&ifp->if_snd)) { |
IF_DROP(&ifp->if_snd); |
splx(s); |
senderr(ENOBUFS); |
} |
IF_ENQUEUE(&ifp->if_snd, m); |
if ((ifp->if_flags & IFF_OACTIVE) == 0) |
(*ifp->if_start)(ifp); |
splx(s); |
ifp->if_obytes += len + sizeof (struct ether_header); |
if (m->m_flags & M_MCAST) |
ifp->if_omcasts++; |
return (error); |
|
bad: |
if (m) |
m_freem(m); |
return (error); |
} |
|
/* |
* Process a received Ethernet packet; |
* the packet is in the mbuf chain m without |
* the ether header, which is provided separately. |
*/ |
void |
ether_input(ifp, eh, m) |
struct ifnet *ifp; |
register struct ether_header *eh; |
struct mbuf *m; |
{ |
register struct ifqueue *inq; |
u_short ether_type; |
#ifdef NS |
u_short *checksum; |
#endif |
int s; |
#if defined (ISO) || defined (LLC) || defined(NETATALK) |
register struct llc *l; |
#endif |
|
if ((ifp->if_flags & IFF_UP) == 0) { |
m_freem(m); |
return; |
} |
ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh); |
if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, |
sizeof(etherbroadcastaddr)) == 0) |
m->m_flags |= M_BCAST; |
else if (eh->ether_dhost[0] & 1) |
m->m_flags |= M_MCAST; |
if (m->m_flags & (M_BCAST|M_MCAST)) |
ifp->if_imcasts++; |
|
/* |
* RTEMS addition -- allow application to `tap into' |
* the incoming packet stream. |
*/ |
if (ifp->if_tap && (*ifp->if_tap)(ifp, eh, m)) { |
m_freem(m); |
return; |
} |
|
ether_type = ntohs(eh->ether_type); |
|
switch (ether_type) { |
#ifdef INET |
case ETHERTYPE_IP: |
schednetisr(NETISR_IP); |
inq = &ipintrq; |
break; |
|
case ETHERTYPE_ARP: |
schednetisr(NETISR_ARP); |
inq = &arpintrq; |
break; |
#endif |
#ifdef IPX |
case ETHERTYPE_IPX: |
schednetisr(NETISR_IPX); |
inq = &ipxintrq; |
break; |
#endif |
#ifdef NS |
case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */ |
schednetisr(NETISR_NS); |
inq = &nsintrq; |
break; |
|
#endif /* NS */ |
#ifdef NETATALK |
case ETHERTYPE_AT: |
schednetisr(NETISR_ATALK); |
inq = &atintrq1; |
break; |
case ETHERTYPE_AARP: |
/* probably this should be done with a NETISR as well */ |
aarpinput((struct arpcom *)ifp, m); /* XXX */ |
return; |
#endif NETATALK |
default: |
#ifdef NS |
checksum = mtod(m, ushort *); |
/* Novell 802.3 */ |
if ((ether_type <= ETHERMTU) && |
((*checksum == 0xffff) || (*checksum == 0xE0E0))){ |
if(*checksum == 0xE0E0) { |
m->m_pkthdr.len -= 3; |
m->m_len -= 3; |
m->m_data += 3; |
} |
schednetisr(NETISR_NS); |
inq = &nsintrq; |
break; |
} |
#endif /* NS */ |
#if defined (ISO) || defined (LLC) || defined(NETATALK) |
if (ether_type > ETHERMTU) |
goto dropanyway; |
l = mtod(m, struct llc *); |
switch (l->llc_dsap) { |
#ifdef NETATALK |
case LLC_SNAP_LSAP: |
switch (l->llc_control) { |
case LLC_UI: |
if (l->llc_ssap != LLC_SNAP_LSAP) |
goto dropanyway; |
|
if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code, |
sizeof(at_org_code)) == 0 && |
ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) { |
inq = &atintrq2; |
m_adj( m, sizeof( struct llc )); |
schednetisr(NETISR_ATALK); |
break; |
} |
|
if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code, |
sizeof(aarp_org_code)) == 0 && |
ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) { |
m_adj( m, sizeof( struct llc )); |
aarpinput((struct arpcom *)ifp, m); /* XXX */ |
return; |
} |
|
default: |
goto dropanyway; |
} |
break; |
#endif NETATALK |
#ifdef ISO |
case LLC_ISO_LSAP: |
switch (l->llc_control) { |
case LLC_UI: |
/* LLC_UI_P forbidden in class 1 service */ |
if ((l->llc_dsap == LLC_ISO_LSAP) && |
(l->llc_ssap == LLC_ISO_LSAP)) { |
/* LSAP for ISO */ |
if (m->m_pkthdr.len > ether_type) |
m_adj(m, ether_type - m->m_pkthdr.len); |
m->m_data += 3; /* XXX */ |
m->m_len -= 3; /* XXX */ |
m->m_pkthdr.len -= 3; /* XXX */ |
M_PREPEND(m, sizeof *eh, M_DONTWAIT); |
if (m == 0) |
return; |
*mtod(m, struct ether_header *) = *eh; |
IFDEBUG(D_ETHER) |
printf("clnp packet"); |
ENDDEBUG |
schednetisr(NETISR_ISO); |
inq = &clnlintrq; |
break; |
} |
goto dropanyway; |
|
case LLC_XID: |
case LLC_XID_P: |
if(m->m_len < 6) |
goto dropanyway; |
l->llc_window = 0; |
l->llc_fid = 9; |
l->llc_class = 1; |
l->llc_dsap = l->llc_ssap = 0; |
/* Fall through to */ |
case LLC_TEST: |
case LLC_TEST_P: |
{ |
struct sockaddr sa; |
register struct ether_header *eh2; |
int i; |
u_char c = l->llc_dsap; |
|
l->llc_dsap = l->llc_ssap; |
l->llc_ssap = c; |
if (m->m_flags & (M_BCAST | M_MCAST)) |
bcopy((caddr_t)ac->ac_enaddr, |
(caddr_t)eh->ether_dhost, 6); |
sa.sa_family = AF_UNSPEC; |
sa.sa_len = sizeof(sa); |
eh2 = (struct ether_header *)sa.sa_data; |
for (i = 0; i < 6; i++) { |
eh2->ether_shost[i] = c = eh->ether_dhost[i]; |
eh2->ether_dhost[i] = |
eh->ether_dhost[i] = eh->ether_shost[i]; |
eh->ether_shost[i] = c; |
} |
ifp->if_output(ifp, m, &sa, NULL); |
return; |
} |
default: |
m_freem(m); |
return; |
} |
break; |
#endif /* ISO */ |
#ifdef LLC |
case LLC_X25_LSAP: |
{ |
if (m->m_pkthdr.len > ether_type) |
m_adj(m, ether_type - m->m_pkthdr.len); |
M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT); |
if (m == 0) |
return; |
if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP, |
eh->ether_dhost, LLC_X25_LSAP, 6, |
mtod(m, struct sdl_hdr *))) |
panic("ETHER cons addr failure"); |
mtod(m, struct sdl_hdr *)->sdlhdr_len = ether_type; |
#ifdef LLC_DEBUG |
printf("llc packet\n"); |
#endif /* LLC_DEBUG */ |
schednetisr(NETISR_CCITT); |
inq = &llcintrq; |
break; |
} |
#endif /* LLC */ |
dropanyway: |
default: |
m_freem(m); |
return; |
} |
#else /* ISO || LLC || NETATALK */ |
m_freem(m); |
return; |
#endif /* ISO || LLC || NETATALK */ |
} |
|
s = splimp(); |
if (IF_QFULL(inq)) { |
IF_DROP(inq); |
m_freem(m); |
} else |
IF_ENQUEUE(inq, m); |
splx(s); |
} |
|
/* |
* Perform common duties while attaching to interface list |
*/ |
void |
ether_ifattach(ifp) |
register struct ifnet *ifp; |
{ |
register struct ifaddr *ifa; |
register struct sockaddr_dl *sdl; |
|
ifp->if_type = IFT_ETHER; |
ifp->if_addrlen = 6; |
ifp->if_hdrlen = 14; |
ifp->if_mtu = ETHERMTU; |
if (ifp->if_baudrate == 0) |
ifp->if_baudrate = 10000000; |
for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) |
if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && |
sdl->sdl_family == AF_LINK) { |
sdl->sdl_type = IFT_ETHER; |
sdl->sdl_alen = ifp->if_addrlen; |
bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr, |
LLADDR(sdl), ifp->if_addrlen); |
break; |
} |
} |
|
static u_char ether_ipmulticast_min[6] = |
{ 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }; |
static u_char ether_ipmulticast_max[6] = |
{ 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff }; |
/* |
* Add an Ethernet multicast address or range of addresses to the list for a |
* given interface. |
*/ |
int |
ether_addmulti(ifr, ac) |
struct ifreq *ifr; |
register struct arpcom *ac; |
{ |
register struct ether_multi *enm; |
struct sockaddr_in *sin; |
u_char addrlo[6]; |
u_char addrhi[6]; |
int set_allmulti = 0; |
int s = splimp(); |
|
switch (ifr->ifr_addr.sa_family) { |
|
case AF_UNSPEC: |
bcopy(ifr->ifr_addr.sa_data, addrlo, 6); |
bcopy(addrlo, addrhi, 6); |
break; |
|
#ifdef INET |
case AF_INET: |
sin = (struct sockaddr_in *)&(ifr->ifr_addr); |
if (sin->sin_addr.s_addr == INADDR_ANY) { |
/* |
* An IP address of INADDR_ANY means listen to all |
* of the Ethernet multicast addresses used for IP. |
* (This is for the sake of IP multicast routers.) |
*/ |
bcopy(ether_ipmulticast_min, addrlo, 6); |
bcopy(ether_ipmulticast_max, addrhi, 6); |
set_allmulti = 1; |
} |
else { |
ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); |
bcopy(addrlo, addrhi, 6); |
} |
break; |
#endif |
|
default: |
splx(s); |
return (EAFNOSUPPORT); |
} |
|
/* |
* Verify that we have valid Ethernet multicast addresses. |
*/ |
if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) { |
splx(s); |
return (EINVAL); |
} |
/* |
* See if the address range is already in the list. |
*/ |
ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); |
if (enm != NULL) { |
/* |
* Found it; just increment the reference count. |
*/ |
++enm->enm_refcount; |
splx(s); |
return (0); |
} |
/* |
* New address or range; malloc a new multicast record |
* and link it into the interface's multicast list. |
*/ |
enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT); |
if (enm == NULL) { |
splx(s); |
return (ENOBUFS); |
} |
bcopy(addrlo, enm->enm_addrlo, 6); |
bcopy(addrhi, enm->enm_addrhi, 6); |
enm->enm_ac = ac; |
enm->enm_refcount = 1; |
enm->enm_next = ac->ac_multiaddrs; |
ac->ac_multiaddrs = enm; |
ac->ac_multicnt++; |
splx(s); |
if (set_allmulti) |
ac->ac_if.if_flags |= IFF_ALLMULTI; |
|
/* |
* Return ENETRESET to inform the driver that the list has changed |
* and its reception filter should be adjusted accordingly. |
*/ |
return (ENETRESET); |
} |
|
/* |
* Delete a multicast address record. |
*/ |
int |
ether_delmulti(ifr, ac) |
struct ifreq *ifr; |
register struct arpcom *ac; |
{ |
register struct ether_multi *enm; |
register struct ether_multi **p; |
struct sockaddr_in *sin; |
u_char addrlo[6]; |
u_char addrhi[6]; |
int unset_allmulti = 0; |
int s = splimp(); |
|
switch (ifr->ifr_addr.sa_family) { |
|
case AF_UNSPEC: |
bcopy(ifr->ifr_addr.sa_data, addrlo, 6); |
bcopy(addrlo, addrhi, 6); |
break; |
|
#ifdef INET |
case AF_INET: |
sin = (struct sockaddr_in *)&(ifr->ifr_addr); |
if (sin->sin_addr.s_addr == INADDR_ANY) { |
/* |
* An IP address of INADDR_ANY means stop listening |
* to the range of Ethernet multicast addresses used |
* for IP. |
*/ |
bcopy(ether_ipmulticast_min, addrlo, 6); |
bcopy(ether_ipmulticast_max, addrhi, 6); |
unset_allmulti = 1; |
} |
else { |
ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); |
bcopy(addrlo, addrhi, 6); |
} |
break; |
#endif |
|
default: |
splx(s); |
return (EAFNOSUPPORT); |
} |
|
/* |
* Look up the address in our list. |
*/ |
ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); |
if (enm == NULL) { |
splx(s); |
return (ENXIO); |
} |
if (--enm->enm_refcount != 0) { |
/* |
* Still some claims to this record. |
*/ |
splx(s); |
return (0); |
} |
/* |
* No remaining claims to this record; unlink and free it. |
*/ |
for (p = &enm->enm_ac->ac_multiaddrs; |
*p != enm; |
p = &(*p)->enm_next) |
continue; |
*p = (*p)->enm_next; |
free(enm, M_IFMADDR); |
ac->ac_multicnt--; |
splx(s); |
if (unset_allmulti) |
ac->ac_if.if_flags &= ~IFF_ALLMULTI; |
|
/* |
* Return ENETRESET to inform the driver that the list has changed |
* and its reception filter should be adjusted accordingly. |
*/ |
return (ENETRESET); |
} |
|
SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet"); |
|
int |
ether_ioctl(struct ifnet *ifp, int command, caddr_t data) |
{ |
struct ifaddr *ifa = (struct ifaddr *) data; |
struct ifreq *ifr = (struct ifreq *) data; |
int error = 0; |
|
switch (command) { |
case SIOCSIFADDR: |
ifp->if_flags |= IFF_UP; |
|
switch (ifa->ifa_addr->sa_family) { |
#ifdef INET |
case AF_INET: |
ifp->if_init(ifp->if_softc); /* before arpwhohas */ |
arp_ifinit((struct arpcom *)ifp, ifa); |
break; |
#endif |
#ifdef IPX |
/* |
* XXX - This code is probably wrong |
*/ |
case AF_IPX: |
{ |
register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr); |
struct arpcom *ac = (struct arpcom *) (ifp->if_softc); |
|
if (ipx_nullhost(*ina)) |
ina->x_host = |
*(union ipx_host *) |
ac->ac_enaddr; |
else { |
bcopy((caddr_t) ina->x_host.c_host, |
(caddr_t) ac->ac_enaddr, |
sizeof(ac->ac_enaddr)); |
} |
|
/* |
* Set new address |
*/ |
ifp->if_init(ifp->if_softc); |
break; |
} |
#endif |
#ifdef NS |
/* |
* XXX - This code is probably wrong |
*/ |
case AF_NS: |
{ |
register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); |
struct arpcom *ac = (struct arpcom *) (ifp->if_softc); |
|
if (ns_nullhost(*ina)) |
ina->x_host = |
*(union ns_host *) (ac->ac_enaddr); |
else { |
bcopy((caddr_t) ina->x_host.c_host, |
(caddr_t) ac->ac_enaddr, |
sizeof(ac->ac_enaddr)); |
} |
|
/* |
* Set new address |
*/ |
ifp->if_init(ifp->if_softc); |
break; |
} |
#endif |
default: |
ifp->if_init(ifp->if_softc); |
break; |
} |
break; |
|
case SIOCGIFADDR: |
{ |
struct sockaddr *sa; |
|
sa = (struct sockaddr *) & ifr->ifr_data; |
bcopy(((struct arpcom *)ifp->if_softc)->ac_enaddr, |
(caddr_t) sa->sa_data, ETHER_ADDR_LEN); |
} |
break; |
|
case SIOCSIFMTU: |
/* |
* Set the interface MTU. |
*/ |
if (ifr->ifr_mtu > ETHERMTU) { |
error = EINVAL; |
} else { |
ifp->if_mtu = ifr->ifr_mtu; |
} |
break; |
} |
return (error); |
} |
/if_dl.h
0,0 → 1,86
/* |
* Copyright (c) 1990, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)if_dl.h 8.1 (Berkeley) 6/10/93 |
* $Id: if_dl.h,v 1.2 2001-09-27 12:01:54 chris Exp $ |
*/ |
|
#ifndef _NET_IF_DL_H_ |
#define _NET_IF_DL_H_ |
|
/* |
* A Link-Level Sockaddr may specify the interface in one of two |
* ways: either by means of a system-provided index number (computed |
* anew and possibly differently on every reboot), or by a human-readable |
* string such as "il0" (for managerial convenience). |
* |
* Census taking actions, such as something akin to SIOCGCONF would return |
* both the index and the human name. |
* |
* High volume transactions (such as giving a link-level ``from'' address |
* in a recvfrom or recvmsg call) may be likely only to provide the indexed |
* form, (which requires fewer copy operations and less space). |
* |
* The form and interpretation of the link-level address is purely a matter |
* of convention between the device driver and its consumers; however, it is |
* expected that all drivers for an interface of a given if_type will agree. |
*/ |
|
/* |
* Structure of a Link-Level sockaddr: |
*/ |
struct sockaddr_dl { |
u_char sdl_len; /* Total length of sockaddr */ |
u_char sdl_family; /* AF_DLI */ |
u_short sdl_index; /* if != 0, system given index for interface */ |
u_char sdl_type; /* interface type */ |
u_char sdl_nlen; /* interface name length, no trailing 0 reqd. */ |
u_char sdl_alen; /* link level address length */ |
u_char sdl_slen; /* link layer selector length */ |
char sdl_data[12]; /* minimum work area, can be larger; |
contains both if name and ll address */ |
}; |
|
#define LLADDR(s) ((caddr_t)((s)->sdl_data + (s)->sdl_nlen)) |
|
#ifndef KERNEL |
|
#include <sys/cdefs.h> |
|
__BEGIN_DECLS |
void link_addr __P((const char *, struct sockaddr_dl *)); |
char *link_ntoa __P((const struct sockaddr_dl *)); |
__END_DECLS |
|
#endif /* !KERNEL */ |
|
#endif |
/if_ppp.h
0,0 → 1,132
/* $Id: if_ppp.h,v 1.2 2001-09-27 12:01:54 chris Exp $ */ |
|
/* |
* if_ppp.h - Point-to-Point Protocol definitions. |
* |
* Copyright (c) 1989 Carnegie Mellon University. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms are permitted |
* provided that the above copyright notice and this paragraph are |
* duplicated in all such forms and that any documentation, |
* advertising materials, and other materials related to such |
* distribution and use acknowledge that the software was developed |
* by Carnegie Mellon University. The name of the |
* University may not be used to endorse or promote products derived |
* from this software without specific prior written permission. |
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
*/ |
|
#ifndef _IF_PPP_H_ |
#define _IF_PPP_H_ |
|
/* |
* Bit definitions for flags. |
*/ |
#define SC_COMP_PROT 0x00000001 /* protocol compression (output) */ |
#define SC_COMP_AC 0x00000002 /* header compression (output) */ |
#define SC_COMP_TCP 0x00000004 /* TCP (VJ) compression (output) */ |
#define SC_NO_TCP_CCID 0x00000008 /* disable VJ connection-id comp. */ |
#define SC_REJ_COMP_AC 0x00000010 /* reject adrs/ctrl comp. on input */ |
#define SC_REJ_COMP_TCP 0x00000020 /* reject TCP (VJ) comp. on input */ |
#define SC_CCP_OPEN 0x00000040 /* Look at CCP packets */ |
#define SC_CCP_UP 0x00000080 /* May send/recv compressed packets */ |
#define SC_DEBUG 0x00010000 /* enable debug messages */ |
#define SC_LOG_INPKT 0x00020000 /* log contents of good pkts recvd */ |
#define SC_LOG_OUTPKT 0x00040000 /* log contents of pkts sent */ |
#define SC_LOG_RAWIN 0x00080000 /* log all chars received */ |
#define SC_LOG_FLUSH 0x00100000 /* log all chars flushed */ |
#define SC_RCV_B7_0 0x01000000 /* have rcvd char with bit 7 = 0 */ |
#define SC_RCV_B7_1 0x02000000 /* have rcvd char with bit 7 = 1 */ |
#define SC_RCV_EVNP 0x04000000 /* have rcvd char with even parity */ |
#define SC_RCV_ODDP 0x08000000 /* have rcvd char with odd parity */ |
#define SC_MASK 0x0fff00ff /* bits that user can change */ |
|
/* |
* State bits in sc_flags, not changeable by user. |
*/ |
#define SC_TIMEOUT 0x00000400 /* timeout is currently pending */ |
#define SC_VJ_RESET 0x00000800 /* need to reset VJ decomp */ |
#define SC_COMP_RUN 0x00001000 /* compressor has been inited */ |
#define SC_DECOMP_RUN 0x00002000 /* decompressor has been inited */ |
#define SC_DC_ERROR 0x00004000 /* non-fatal decomp error detected */ |
#define SC_DC_FERROR 0x00008000 /* fatal decomp error detected */ |
#define SC_TBUSY 0x10000000 /* xmitter doesn't need a packet yet */ |
#define SC_PKTLOST 0x20000000 /* have lost or dropped a packet */ |
#define SC_FLUSH 0x40000000 /* flush input until next PPP_FLAG */ |
#define SC_ESCAPED 0x80000000 /* saw a PPP_ESCAPE */ |
|
/* |
* Ioctl definitions. |
*/ |
|
struct npioctl { |
int protocol; /* PPP procotol, e.g. PPP_IP */ |
enum NPmode mode; |
}; |
|
/* Structure describing a CCP configuration option, for PPPIOCSCOMPRESS */ |
struct ppp_option_data { |
u_char *ptr; |
u_int length; |
int transmit; |
}; |
|
struct ifpppstatsreq { |
char ifr_name[IFNAMSIZ]; |
struct ppp_stats stats; |
}; |
|
struct ifpppcstatsreq { |
char ifr_name[IFNAMSIZ]; |
struct ppp_comp_stats stats; |
}; |
|
/* |
* Ioctl definitions. |
*/ |
|
#define PPPIOCGFLAGS _IOR('t', 90, int) /* get configuration flags */ |
#define PPPIOCSFLAGS _IOW('t', 89, int) /* set configuration flags */ |
#define PPPIOCGASYNCMAP _IOR('t', 88, int) /* get async map */ |
#define PPPIOCSASYNCMAP _IOW('t', 87, int) /* set async map */ |
#define PPPIOCGUNIT _IOR('t', 86, int) /* get ppp unit number */ |
#define PPPIOCGRASYNCMAP _IOR('t', 85, int) /* get receive async map */ |
#define PPPIOCSRASYNCMAP _IOW('t', 84, int) /* set receive async map */ |
#define PPPIOCGMRU _IOR('t', 83, int) /* get max receive unit */ |
#define PPPIOCSMRU _IOW('t', 82, int) /* set max receive unit */ |
#define PPPIOCSMAXCID _IOW('t', 81, int) /* set VJ max slot ID */ |
#define PPPIOCGXASYNCMAP _IOR('t', 80, ext_accm) /* get extended ACCM */ |
#define PPPIOCSXASYNCMAP _IOW('t', 79, ext_accm) /* set extended ACCM */ |
#define PPPIOCXFERUNIT _IO('t', 78) /* transfer PPP unit */ |
#define PPPIOCSCOMPRESS _IOW('t', 77, struct ppp_option_data) |
#define PPPIOCGNPMODE _IOWR('t', 76, struct npioctl) /* get NP mode */ |
#define PPPIOCSNPMODE _IOW('t', 75, struct npioctl) /* set NP mode */ |
#define PPPIOCGIDLE _IOR('t', 74, struct ppp_idle) /* get idle time */ |
#ifdef PPP_FILTER |
#define PPPIOCSPASS _IOW('t', 71, struct bpf_program) /* set pass filter */ |
#define PPPIOCSACTIVE _IOW('t', 70, struct bpf_program) /* set active filt */ |
#endif /* PPP_FILTER */ |
|
/* PPPIOC[GS]MTU are alternatives to SIOC[GS]IFMTU, used under Ultrix */ |
#define PPPIOCGMTU _IOR('t', 73, int) /* get interface MTU */ |
#define PPPIOCSMTU _IOW('t', 72, int) /* set interface MTU */ |
|
/* |
* These two are interface ioctls so that pppstats can do them on |
* a socket without having to open the serial device. |
*/ |
#define SIOCGPPPSTATS _IOWR('i', 123, struct ifpppstatsreq) |
#define SIOCGPPPCSTATS _IOWR('i', 122, struct ifpppcstatsreq) |
|
#if !defined(ifr_mtu) |
#define ifr_mtu ifr_ifru.ifru_metric |
#endif |
|
#if (defined(_KERNEL) || defined(KERNEL)) && !defined(NeXT) |
void pppattach __P((void)); |
void pppintr __P((void)); |
#endif |
#endif /* _IF_PPP_H_ */ |
/ethernet.h
0,0 → 1,63
/* |
* Fundamental constants relating to ethernet. |
* |
* $Id: ethernet.h,v 1.2 2001-09-27 12:01:54 chris Exp $ |
* |
*/ |
|
#ifndef _NET_ETHERNET_H_ |
#define _NET_ETHERNET_H_ |
|
/* |
* The number of bytes in an ethernet (MAC) address. |
*/ |
#define ETHER_ADDR_LEN 6 |
|
/* |
* The number of bytes in the type field. |
*/ |
#define ETHER_TYPE_LEN 2 |
|
/* |
* The number of bytes in the trailing CRC field. |
*/ |
#define ETHER_CRC_LEN 4 |
|
/* |
* The length of the combined header. |
*/ |
#define ETHER_HDR_LEN (ETHER_ADDR_LEN*2+ETHER_TYPE_LEN) |
|
/* |
* The minimum packet length. |
*/ |
#define ETHER_MIN_LEN 64 |
|
/* |
* The maximum packet length. |
*/ |
#define ETHER_MAX_LEN 1518 |
|
/* |
* A macro to validate a length with |
*/ |
#define ETHER_IS_VALID_LEN(foo) \ |
((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN) |
|
/* |
* Structure of a 10Mb/s Ethernet header. |
*/ |
struct ether_header { |
u_char ether_dhost[ETHER_ADDR_LEN]; |
u_char ether_shost[ETHER_ADDR_LEN]; |
u_short ether_type; |
}; |
|
/* |
* Structure of a 48-bit Ethernet address. |
*/ |
struct ether_addr { |
u_char octet[ETHER_ADDR_LEN]; |
}; |
|
#endif |
/if_types.h
0,0 → 1,101
/* |
* Copyright (c) 1989, 1993, 1994 |
* The Regents of the University of California. All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)if_types.h 8.2 (Berkeley) 4/20/94 |
* $Id: if_types.h,v 1.2 2001-09-27 12:01:54 chris Exp $ |
*/ |
|
#ifndef _NET_IF_TYPES_H_ |
#define _NET_IF_TYPES_H_ |
|
/* |
* Interface types for benefit of parsing media address headers. |
* This list is derived from the SNMP list of ifTypes, currently |
* documented in RFC1573. |
*/ |
|
#define IFT_OTHER 0x1 /* none of the following */ |
#define IFT_1822 0x2 /* old-style arpanet imp */ |
#define IFT_HDH1822 0x3 /* HDH arpanet imp */ |
#define IFT_X25DDN 0x4 /* x25 to imp */ |
#define IFT_X25 0x5 /* PDN X25 interface (RFC877) */ |
#define IFT_ETHER 0x6 /* Ethernet CSMACD */ |
#define IFT_ISO88023 0x7 /* CMSA CD */ |
#define IFT_ISO88024 0x8 /* Token Bus */ |
#define IFT_ISO88025 0x9 /* Token Ring */ |
#define IFT_ISO88026 0xa /* MAN */ |
#define IFT_STARLAN 0xb |
#define IFT_P10 0xc /* Proteon 10MBit ring */ |
#define IFT_P80 0xd /* Proteon 80MBit ring */ |
#define IFT_HY 0xe /* Hyperchannel */ |
#define IFT_FDDI 0xf |
#define IFT_LAPB 0x10 |
#define IFT_SDLC 0x11 |
#define IFT_T1 0x12 |
#define IFT_CEPT 0x13 /* E1 - european T1 */ |
#define IFT_ISDNBASIC 0x14 |
#define IFT_ISDNPRIMARY 0x15 |
#define IFT_PTPSERIAL 0x16 /* Proprietary PTP serial */ |
#define IFT_PPP 0x17 /* RFC 1331 */ |
#define IFT_LOOP 0x18 /* loopback */ |
#define IFT_EON 0x19 /* ISO over IP */ |
#define IFT_XETHER 0x1a /* obsolete 3MB experimental ethernet */ |
#define IFT_NSIP 0x1b /* XNS over IP */ |
#define IFT_SLIP 0x1c /* IP over generic TTY */ |
#define IFT_ULTRA 0x1d /* Ultra Technologies */ |
#define IFT_DS3 0x1e /* Generic T3 */ |
#define IFT_SIP 0x1f /* SMDS */ |
#define IFT_FRELAY 0x20 /* Frame Relay DTE only */ |
#define IFT_RS232 0x21 |
#define IFT_PARA 0x22 /* parallel-port */ |
#define IFT_ARCNET 0x23 |
#define IFT_ARCNETPLUS 0x24 |
#define IFT_ATM 0x25 /* ATM cells */ |
#define IFT_MIOX25 0x26 |
#define IFT_SONET 0x27 /* SONET or SDH */ |
#define IFT_X25PLE 0x28 |
#define IFT_ISO88022LLC 0x29 |
#define IFT_LOCALTALK 0x2a |
#define IFT_SMDSDXI 0x2b |
#define IFT_FRELAYDCE 0x2c /* Frame Relay DCE */ |
#define IFT_V35 0x2d |
#define IFT_HSSI 0x2e |
#define IFT_HIPPI 0x2f |
#define IFT_MODEM 0x30 /* Generic Modem */ |
#define IFT_AAL5 0x31 /* AAL5 over ATM */ |
#define IFT_SONETPATH 0x32 |
#define IFT_SONETVT 0x33 |
#define IFT_SMDSICIP 0x34 /* SMDS InterCarrier Interface */ |
#define IFT_PROPVIRTUAL 0x35 /* Proprietary Virtual/internal */ |
#define IFT_PROPMUX 0x36 /* Proprietary Multiplexing */ |
|
#endif |
/if_loop.c
0,0 → 1,302
/* |
* Copyright (c) 1982, 1986, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)if_loop.c 8.1 (Berkeley) 6/10/93 |
* $Id: if_loop.c,v 1.2 2001-09-27 12:01:54 chris Exp $ |
*/ |
|
/* |
* Loopback interface driver for protocol testing and timing. |
*/ |
#include "loop.h" |
#if NLOOP > 0 |
|
#include <sys/param.h> |
#include <sys/systm.h> |
#include <sys/kernel.h> |
#include <sys/mbuf.h> |
#include <sys/socket.h> |
#include <sys/errno.h> |
#include <sys/ioctl.h> |
#include <sys/time.h> |
|
#include <net/if.h> |
#include <net/if_types.h> |
#include <net/netisr.h> |
#include <net/route.h> |
#include <net/bpf.h> |
|
#ifdef INET |
#include <netinet/in.h> |
#include <netinet/in_systm.h> |
#include <netinet/in_var.h> |
#include <netinet/ip.h> |
#endif |
|
#ifdef IPX |
#include <netipx/ipx.h> |
#include <netipx/ipx_if.h> |
#endif |
|
#ifdef NS |
#include <netns/ns.h> |
#include <netns/ns_if.h> |
#endif |
|
#ifdef ISO |
#include <netiso/iso.h> |
#include <netiso/iso_var.h> |
#endif |
|
#ifdef NETATALK |
#include <netinet/if_ether.h> |
#include <netatalk/at.h> |
#include <netatalk/at_var.h> |
#endif NETATALK |
|
#include "bpfilter.h" |
|
static int loioctl __P((struct ifnet *, int, caddr_t)); |
static void lortrequest __P((int, struct rtentry *, struct sockaddr *)); |
|
void rtems_bsdnet_loopattach __P((void *)); |
PSEUDO_SET(loopattach, if_loop); |
|
#ifdef TINY_LOMTU |
#define LOMTU (1024+512) |
#else |
#define LOMTU 16384 |
#endif |
|
struct ifnet loif[NLOOP]; |
|
/* ARGSUSED */ |
void |
rtems_bsdnet_loopattach(dummy) |
void *dummy; |
{ |
register struct ifnet *ifp; |
register int i = 0; |
|
for (ifp = loif; i < NLOOP; ifp++) { |
ifp->if_name = "lo"; |
ifp->if_next = NULL; |
ifp->if_unit = i++; |
ifp->if_mtu = LOMTU; |
ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST; |
ifp->if_ioctl = loioctl; |
ifp->if_output = looutput; |
ifp->if_type = IFT_LOOP; |
ifp->if_hdrlen = 0; |
ifp->if_addrlen = 0; |
ifp->if_snd.ifq_maxlen = ifqmaxlen; |
if_attach(ifp); |
#if NBPFILTER > 0 |
bpfattach(ifp, DLT_NULL, sizeof(u_int)); |
#endif |
} |
} |
|
int |
looutput(ifp, m, dst, rt) |
struct ifnet *ifp; |
register struct mbuf *m; |
struct sockaddr *dst; |
register struct rtentry *rt; |
{ |
int s, isr; |
register struct ifqueue *ifq = 0; |
|
if ((m->m_flags & M_PKTHDR) == 0) |
panic("looutput no HDR"); |
#if NBPFILTER > 0 |
/* BPF write needs to be handled specially */ |
if (dst->sa_family == AF_UNSPEC) { |
dst->sa_family = *(mtod(m, int *)); |
m->m_len -= sizeof(int); |
m->m_pkthdr.len -= sizeof(int); |
m->m_data += sizeof(int); |
} |
|
if (ifp->if_bpf) { |
/* |
* We need to prepend the address family as |
* a four byte field. Cons up a dummy header |
* to pacify bpf. This is safe because bpf |
* will only read from the mbuf (i.e., it won't |
* try to free it or keep a pointer a to it). |
*/ |
struct mbuf m0; |
u_int af = dst->sa_family; |
|
m0.m_next = m; |
m0.m_len = 4; |
m0.m_data = (char *)⁡ |
|
bpf_mtap(ifp, &m0); |
} |
#endif |
m->m_pkthdr.rcvif = ifp; |
|
if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { |
m_freem(m); |
return (rt->rt_flags & RTF_BLACKHOLE ? 0 : |
rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); |
} |
ifp->if_opackets++; |
ifp->if_obytes += m->m_pkthdr.len; |
switch (dst->sa_family) { |
|
#ifdef INET |
case AF_INET: |
ifq = &ipintrq; |
isr = NETISR_IP; |
break; |
#endif |
#ifdef IPX |
case AF_IPX: |
ifq = &ipxintrq; |
isr = NETISR_IPX; |
break; |
#endif |
#ifdef NS |
case AF_NS: |
ifq = &nsintrq; |
isr = NETISR_NS; |
break; |
#endif |
#ifdef ISO |
case AF_ISO: |
ifq = &clnlintrq; |
isr = NETISR_ISO; |
break; |
#endif |
#ifdef NETATALK |
case AF_APPLETALK: |
ifq = &atintrq2; |
isr = NETISR_ATALK; |
break; |
#endif NETATALK |
default: |
printf("lo%d: can't handle af%d\n", ifp->if_unit, |
dst->sa_family); |
m_freem(m); |
return (EAFNOSUPPORT); |
} |
s = splimp(); |
if (IF_QFULL(ifq)) { |
IF_DROP(ifq); |
m_freem(m); |
splx(s); |
return (ENOBUFS); |
} |
IF_ENQUEUE(ifq, m); |
schednetisr(isr); |
ifp->if_ipackets++; |
ifp->if_ibytes += m->m_pkthdr.len; |
splx(s); |
return (0); |
} |
|
/* ARGSUSED */ |
static void |
lortrequest(cmd, rt, sa) |
int cmd; |
struct rtentry *rt; |
struct sockaddr *sa; |
{ |
if (rt) { |
rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; /* for ISO */ |
/* |
* For optimal performance, the send and receive buffers |
* should be at least twice the MTU plus a little more for |
* overhead. |
*/ |
rt->rt_rmx.rmx_recvpipe = |
rt->rt_rmx.rmx_sendpipe = 3 * LOMTU; |
} |
} |
|
/* |
* Process an ioctl request. |
*/ |
/* ARGSUSED */ |
static int |
loioctl(ifp, cmd, data) |
register struct ifnet *ifp; |
int cmd; |
caddr_t data; |
{ |
register struct ifaddr *ifa; |
register struct ifreq *ifr = (struct ifreq *)data; |
register int error = 0; |
|
switch (cmd) { |
|
case SIOCSIFADDR: |
ifp->if_flags |= IFF_UP | IFF_RUNNING; |
ifa = (struct ifaddr *)data; |
ifa->ifa_rtrequest = lortrequest; |
/* |
* Everything else is done at a higher level. |
*/ |
break; |
|
case SIOCADDMULTI: |
case SIOCDELMULTI: |
if (ifr == 0) { |
error = EAFNOSUPPORT; /* XXX */ |
break; |
} |
switch (ifr->ifr_addr.sa_family) { |
|
#ifdef INET |
case AF_INET: |
break; |
#endif |
|
default: |
error = EAFNOSUPPORT; |
break; |
} |
break; |
|
case SIOCSIFMTU: |
ifp->if_mtu = ifr->ifr_mtu; |
break; |
|
default: |
error = EINVAL; |
} |
return (error); |
} |
#endif /* NLOOP > 0 */ |
/Makefile.am
0,0 → 1,49
## |
## $Id: Makefile.am,v 1.2 2001-09-27 12:01:54 chris Exp $ |
## |
|
AUTOMAKE_OPTIONS = foreign 1.4 |
|
LIBNAME = lib.a |
LIB = $(ARCH)/$(LIBNAME) |
|
C_FILES = if.c if_ethersubr.c if_loop.c radix.c route.c rtsock.c raw_cb.c \ |
raw_usrreq.c |
C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o) |
|
OBJS = $(C_O_FILES) |
|
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg |
include $(top_srcdir)/../../../automake/lib.am |
|
# |
# Add local stuff here using += |
# |
|
AM_CPPFLAGS += -D_COMPILING_BSD_KERNEL_ -DKERNEL -DINET -DNFS -DDIAGNOSTIC \ |
-DBOOTP_COMPAT |
|
$(LIB): $(OBJS) |
$(make-library) |
|
all-local: $(PREINSTALL_FILES) $(ARCH) $(OBJS) $(LIB) |
|
.PRECIOUS: $(LIB) |
|
EXTRA_DIST = if.c if_ethersubr.c if_loop.c \ |
radix.c raw_cb.c raw_usrreq.c route.c rtsock.c |
|
H_FILES = bpf.h ethernet.h if.h if_arp.h if_dl.h if_llc.h if_ppp.h if_types.h \ |
netisr.h ppp-comp.h ppp_defs.h radix.h raw_cb.h route.h |
|
noinst_HEADERS = $(H_FILES) |
|
PREINSTALL_FILES += $(PROJECT_INCLUDE)/net $(H_FILES:%=$(PROJECT_INCLUDE)/net/%) |
|
$(PROJECT_INCLUDE)/net: |
@$(mkinstalldirs) $@ |
|
$(PROJECT_INCLUDE)/net/%.h: %.h |
$(INSTALL_DATA) $< $@ |
|
include $(top_srcdir)/../../../automake/local.am |
/raw_usrreq.c
0,0 → 1,315
/* |
* Copyright (c) 1980, 1986, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)raw_usrreq.c 8.1 (Berkeley) 6/10/93 |
* $Id: raw_usrreq.c,v 1.2 2001-09-27 12:01:54 chris Exp $ |
*/ |
|
#include <sys/param.h> |
#include <sys/queue.h> |
#include <sys/systm.h> |
#include <sys/mbuf.h> |
#include <sys/domain.h> |
#include <sys/protosw.h> |
#include <sys/socket.h> |
#include <sys/socketvar.h> |
#include <sys/errno.h> |
|
#include <net/if.h> |
#include <net/route.h> |
#include <net/netisr.h> |
#include <net/raw_cb.h> |
|
/* |
* Initialize raw connection block q. |
*/ |
void |
raw_init() |
{ |
|
rawcb.rcb_next = rawcb.rcb_prev = &rawcb; |
} |
|
|
/* |
* Raw protocol input routine. Find the socket |
* associated with the packet(s) and move them over. If |
* nothing exists for this packet, drop it. |
*/ |
/* |
* Raw protocol interface. |
*/ |
void |
raw_input(m0, proto, src, dst) |
struct mbuf *m0; |
register struct sockproto *proto; |
struct sockaddr *src, *dst; |
{ |
register struct rawcb *rp; |
register struct mbuf *m = m0; |
register int sockets = 0; |
struct socket *last; |
|
last = 0; |
for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { |
if (rp->rcb_proto.sp_family != proto->sp_family) |
continue; |
if (rp->rcb_proto.sp_protocol && |
rp->rcb_proto.sp_protocol != proto->sp_protocol) |
continue; |
/* |
* We assume the lower level routines have |
* placed the address in a canonical format |
* suitable for a structure comparison. |
* |
* Note that if the lengths are not the same |
* the comparison will fail at the first byte. |
*/ |
#define equal(a1, a2) \ |
(bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0) |
if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst)) |
continue; |
if (rp->rcb_faddr && !equal(rp->rcb_faddr, src)) |
continue; |
if (last) { |
struct mbuf *n; |
n = m_copy(m, 0, (int)M_COPYALL); |
if (n) { |
if (sbappendaddr(&last->so_rcv, src, |
n, (struct mbuf *)0) == 0) |
/* should notify about lost packet */ |
m_freem(n); |
else { |
sorwakeup(last); |
sockets++; |
} |
} |
} |
last = rp->rcb_socket; |
} |
if (last) { |
if (sbappendaddr(&last->so_rcv, src, |
m, (struct mbuf *)0) == 0) |
m_freem(m); |
else { |
sorwakeup(last); |
sockets++; |
} |
} else |
m_freem(m); |
} |
|
/*ARGSUSED*/ |
void |
raw_ctlinput(cmd, arg, dummy) |
int cmd; |
struct sockaddr *arg; |
void *dummy; |
{ |
|
if (cmd < 0 || cmd > PRC_NCMDS) |
return; |
/* INCOMPLETE */ |
} |
|
/*ARGSUSED*/ |
int |
raw_usrreq(so, req, m, nam, control) |
struct socket *so; |
int req; |
struct mbuf *m, *nam, *control; |
{ |
register struct rawcb *rp = sotorawcb(so); |
register int error = 0; |
int len; |
|
if (req == PRU_CONTROL) |
return (EOPNOTSUPP); |
if (control && control->m_len) { |
error = EOPNOTSUPP; |
goto release; |
} |
if (rp == 0) { |
error = EINVAL; |
goto release; |
} |
switch (req) { |
|
/* |
* Allocate a raw control block and fill in the |
* necessary info to allow packets to be routed to |
* the appropriate raw interface routine. |
*/ |
case PRU_ATTACH: |
if ((so->so_state & SS_PRIV) == 0) { |
error = EACCES; |
break; |
} |
error = raw_attach(so, (int)nam); |
break; |
|
/* |
* Destroy state just before socket deallocation. |
* Flush data or not depending on the options. |
*/ |
case PRU_DETACH: |
if (rp == 0) { |
error = ENOTCONN; |
break; |
} |
raw_detach(rp); |
break; |
|
/* |
* If a socket isn't bound to a single address, |
* the raw input routine will hand it anything |
* within that protocol family (assuming there's |
* nothing else around it should go to). |
*/ |
case PRU_CONNECT: |
error = EINVAL; |
#if 0 |
if (rp->rcb_faddr) { |
error = EISCONN; |
break; |
} |
nam = m_copym(nam, 0, M_COPYALL, M_WAIT); |
rp->rcb_faddr = mtod(nam, struct sockaddr *); |
soisconnected(so); |
#endif |
break; |
|
case PRU_BIND: |
error = EINVAL; |
#if 0 |
if (rp->rcb_laddr) { |
error = EINVAL; /* XXX */ |
break; |
} |
error = raw_bind(so, nam); |
#endif |
break; |
|
case PRU_CONNECT2: |
error = EOPNOTSUPP; |
goto release; |
|
case PRU_DISCONNECT: |
if (rp->rcb_faddr == 0) { |
error = ENOTCONN; |
break; |
} |
raw_disconnect(rp); |
soisdisconnected(so); |
break; |
|
/* |
* Mark the connection as being incapable of further input. |
*/ |
case PRU_SHUTDOWN: |
socantsendmore(so); |
break; |
|
/* |
* Ship a packet out. The appropriate raw output |
* routine handles any massaging necessary. |
*/ |
case PRU_SEND: |
if (nam) { |
if (rp->rcb_faddr) { |
error = EISCONN; |
break; |
} |
rp->rcb_faddr = mtod(nam, struct sockaddr *); |
} else if (rp->rcb_faddr == 0) { |
error = ENOTCONN; |
break; |
} |
error = (*so->so_proto->pr_output)(m, so); |
m = NULL; |
if (nam) |
rp->rcb_faddr = 0; |
break; |
|
case PRU_ABORT: |
raw_disconnect(rp); |
sofree(so); |
soisdisconnected(so); |
break; |
|
case PRU_SENSE: |
/* |
* stat: don't bother with a blocksize. |
*/ |
return (0); |
|
/* |
* Not supported. |
*/ |
case PRU_RCVOOB: |
case PRU_RCVD: |
return(EOPNOTSUPP); |
|
case PRU_LISTEN: |
case PRU_ACCEPT: |
case PRU_SENDOOB: |
error = EOPNOTSUPP; |
break; |
|
case PRU_SOCKADDR: |
if (rp->rcb_laddr == 0) { |
error = EINVAL; |
break; |
} |
len = rp->rcb_laddr->sa_len; |
bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len); |
nam->m_len = len; |
break; |
|
case PRU_PEERADDR: |
if (rp->rcb_faddr == 0) { |
error = ENOTCONN; |
break; |
} |
len = rp->rcb_faddr->sa_len; |
bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len); |
nam->m_len = len; |
break; |
|
default: |
panic("raw_usrreq"); |
} |
release: |
if (m != NULL) |
m_freem(m); |
return (error); |
} |
/if_llc.h
0,0 → 1,145
/* |
* Copyright (c) 1988, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)if_llc.h 8.1 (Berkeley) 6/10/93 |
* $Id: if_llc.h,v 1.2 2001-09-27 12:01:54 chris Exp $ |
*/ |
|
#ifndef _NET_IF_LLC_H_ |
#define _NET_IF_LLC_H_ |
|
/* |
* IEEE 802.2 Link Level Control headers, for use in conjunction with |
* 802.{3,4,5} media access control methods. |
* |
* Headers here do not use bit fields due to shortcomings in many |
* compilers. |
*/ |
|
struct llc { |
u_char llc_dsap; |
u_char llc_ssap; |
union { |
struct { |
u_char control; |
u_char format_id; |
u_char class; |
u_char window_x2; |
} type_u; |
struct { |
u_char num_snd_x2; |
u_char num_rcv_x2; |
} type_i; |
struct { |
u_char control; |
u_char num_rcv_x2; |
} type_s; |
struct { |
u_char control; |
struct frmrinfo { |
u_char rej_pdu_0; |
u_char rej_pdu_1; |
u_char frmr_control; |
u_char frmr_control_ext; |
u_char frmr_cause; |
} frmrinfo; |
} type_frmr; |
struct { |
u_char control; |
u_char org_code[3]; |
u_short ether_type; |
} type_snap; |
struct { |
u_char control; |
u_char control_ext; |
} type_raw; |
} llc_un; |
}; |
#define llc_control llc_un.type_u.control |
#define llc_control_ext llc_un.type_raw.control_ext |
#define llc_fid llc_un.type_u.format_id |
#define llc_class llc_un.type_u.class |
#define llc_window llc_un.type_u.window_x2 |
#define llc_frmrinfo llc_un.type_frmr.frmrinfo |
#define llc_frmr_pdu0 llc_un.type_frmr.frmrinfo.rej_pdu0 |
#define llc_frmr_pdu1 llc_un.type_frmr.frmrinfo.rej_pdu1 |
#define llc_frmr_control llc_un.type_frmr.frmrinfo.frmr_control |
#define llc_frmr_control_ext llc_un.type_frmr.frmrinfo.frmr_control_ext |
#define llc_frmr_cause llc_un.type_frmr.frmrinfo.frmr_control_ext |
|
/* |
* Don't use sizeof(struct llc_un) for LLC header sizes |
*/ |
#define LLC_ISFRAMELEN 4 |
#define LLC_UFRAMELEN 3 |
#define LLC_FRMRLEN 7 |
|
/* |
* Unnumbered LLC format commands |
*/ |
#define LLC_UI 0x3 |
#define LLC_UI_P 0x13 |
#define LLC_DISC 0x43 |
#define LLC_DISC_P 0x53 |
#define LLC_UA 0x63 |
#define LLC_UA_P 0x73 |
#define LLC_TEST 0xe3 |
#define LLC_TEST_P 0xf3 |
#define LLC_FRMR 0x87 |
#define LLC_FRMR_P 0x97 |
#define LLC_DM 0x0f |
#define LLC_DM_P 0x1f |
#define LLC_XID 0xaf |
#define LLC_XID_P 0xbf |
#define LLC_SABME 0x6f |
#define LLC_SABME_P 0x7f |
|
/* |
* Supervisory LLC commands |
*/ |
#define LLC_RR 0x01 |
#define LLC_RNR 0x05 |
#define LLC_REJ 0x09 |
|
/* |
* Info format - dummy only |
*/ |
#define LLC_INFO 0x00 |
|
/* |
* ISO PDTR 10178 contains among others |
*/ |
#define LLC_X25_LSAP 0x7e |
#define LLC_SNAP_LSAP 0xaa |
#define LLC_ISO_LSAP 0xfe |
|
#endif |
/raw_cb.c
0,0 → 1,148
/* |
* Copyright (c) 1980, 1986, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)raw_cb.c 8.1 (Berkeley) 6/10/93 |
* $Id: raw_cb.c,v 1.2 2001-09-27 12:01:54 chris Exp $ |
*/ |
|
#include <sys/param.h> |
#include <sys/queue.h> |
#include <sys/systm.h> |
#include <sys/mbuf.h> |
#include <sys/socket.h> |
#include <sys/socketvar.h> |
#include <sys/domain.h> |
#include <sys/protosw.h> |
#include <sys/errno.h> |
|
#include <net/if.h> |
#include <net/route.h> |
#include <net/raw_cb.h> |
#include <netinet/in.h> |
|
/* |
* Routines to manage the raw protocol control blocks. |
* |
* TODO: |
* hash lookups by protocol family/protocol + address family |
* take care of unique address problems per AF? |
* redo address binding to allow wildcards |
*/ |
|
struct rawcb rawcb; |
static u_long raw_sendspace = RAWSNDQ; |
static u_long raw_recvspace = RAWRCVQ; |
|
/* |
* Allocate a control block and a nominal amount |
* of buffer space for the socket. |
*/ |
int |
raw_attach(so, proto) |
register struct socket *so; |
int proto; |
{ |
register struct rawcb *rp = sotorawcb(so); |
int error; |
|
/* |
* It is assumed that raw_attach is called |
* after space has been allocated for the |
* rawcb. |
*/ |
if (rp == 0) |
return (ENOBUFS); |
error = soreserve(so, raw_sendspace, raw_recvspace); |
if (error) |
return (error); |
rp->rcb_socket = so; |
rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family; |
rp->rcb_proto.sp_protocol = proto; |
insque(rp, &rawcb); |
return (0); |
} |
|
/* |
* Detach the raw connection block and discard |
* socket resources. |
*/ |
void |
raw_detach(rp) |
register struct rawcb *rp; |
{ |
struct socket *so = rp->rcb_socket; |
|
so->so_pcb = 0; |
sofree(so); |
remque(rp); |
#ifdef notdef |
if (rp->rcb_laddr) |
m_freem(dtom(rp->rcb_laddr)); |
rp->rcb_laddr = 0; |
#endif |
free((caddr_t)(rp), M_PCB); |
} |
|
/* |
* Disconnect and possibly release resources. |
*/ |
void |
raw_disconnect(rp) |
struct rawcb *rp; |
{ |
|
#ifdef notdef |
if (rp->rcb_faddr) |
m_freem(dtom(rp->rcb_faddr)); |
rp->rcb_faddr = 0; |
#endif |
if (rp->rcb_socket->so_state & SS_NOFDREF) |
raw_detach(rp); |
} |
|
#ifdef notdef |
int |
raw_bind(so, nam) |
register struct socket *so; |
struct mbuf *nam; |
{ |
struct sockaddr *addr = mtod(nam, struct sockaddr *); |
register struct rawcb *rp; |
|
if (ifnet == 0) |
return (EADDRNOTAVAIL); |
rp = sotorawcb(so); |
nam = m_copym(nam, 0, M_COPYALL, M_WAITOK); |
rp->rcb_laddr = mtod(nam, struct sockaddr *); |
return (0); |
} |
#endif |