1#include <sys/types.h>
2#include <sys/param.h>
3#include <sys/socket.h>
4#include <sys/cmn_err.h>
5#include <sys/kmem.h>
6#include <net/route.h>
7#include <netatalk/at.h>
8#include <errno.h>
9
10#include "rt.h"
11
12struct rtab {
13    struct rtab		*r_next, *r_prev;
14    struct sockaddr_at	r_dst;
15    struct sockaddr_at	r_gate;
16};
17
18static struct rtab	*rt_net = NULL;
19static struct rtab	*rt_host = NULL;
20
21    int
22rt_add( struct sockaddr_at *dst, struct sockaddr_at *gate, int flags )
23{
24    struct rtab		*r;
25    struct rtab		*rtab;
26
27    if ( flags & RTF_HOST ) {
28	rtab = rt_host;
29    } else {
30	rtab = rt_net;
31    }
32    for ( r = rtab; r != NULL; r = r->r_next ) {
33	if (( r->r_dst.sat_addr.s_net == dst->sat_addr.s_net ) &&
34		(( flags & RTF_HOST ) ?
35		r->r_dst.sat_addr.s_node == dst->sat_addr.s_node : 1 )) {
36	    return( EEXIST );
37	}
38    }
39
40    if (( r = kmem_alloc( sizeof( struct rtab ), KM_NOSLEEP )) == NULL ) {
41	return( ENOMEM );
42    }
43    r->r_dst = *dst;
44    r->r_gate = *gate;
45
46    r->r_prev = NULL;
47    r->r_next = rtab;
48    if ( rtab != NULL ) {
49	rtab->r_prev = r;
50    }
51    if ( flags & RTF_HOST ) {
52	rt_host = r;
53    } else {
54	rt_net = r;
55    }
56    return( 0 );
57}
58
59    int
60rt_del( struct sockaddr_at *dst, struct sockaddr_at *gate, int flags )
61{
62    struct rtab		*r;
63    struct rtab		*rtab;
64
65    if ( flags & RTF_HOST ) {
66	rtab = rt_host;
67    } else {
68	rtab = rt_net;
69    }
70    for ( r = rtab; r != NULL; r = r->r_next ) {
71	if (( r->r_dst.sat_addr.s_net == dst->sat_addr.s_net ) &&
72		(( flags & RTF_HOST ) ?
73		r->r_dst.sat_addr.s_node == dst->sat_addr.s_node : 1 )) {
74	    break;
75	}
76    }
77    if ( r == NULL ) {
78	return( ESRCH );
79    }
80
81    if ( r == rtab ) {
82	if ( flags & RTF_HOST ) {
83	    rt_host = r->r_next;
84	} else {
85	    rt_net = r->r_next;
86	}
87    }
88    if ( r->r_next != NULL ) {
89	r->r_next->r_prev = r->r_prev;
90    }
91    if ( r->r_prev != NULL ) {
92	r->r_prev->r_next = r->r_next;
93    }
94    kmem_free( r, sizeof( struct rtab ));
95    return( 0 );
96}
97
98    int
99rt_gate( struct sockaddr_at *dst, struct sockaddr_at *gate )
100{
101    struct rtab		*r;
102
103    for ( r = rt_host; r != NULL; r = r->r_next ) {
104	if ( r->r_dst.sat_addr.s_net == dst->sat_addr.s_net &&
105		r->r_dst.sat_addr.s_node == dst->sat_addr.s_node ) {
106	    break;
107	}
108    }
109    if ( r != NULL ) {
110	*gate = r->r_gate;
111	return( 0 );
112    }
113
114    for ( r = rt_net; r != NULL; r = r->r_next ) {
115	if ( r->r_dst.sat_addr.s_net == dst->sat_addr.s_net ) {
116	    break;
117	}
118    }
119    if ( r == NULL ) {
120	return( -1 );
121    }
122
123    *gate = r->r_gate;
124    return( 0 );
125}
126