declare Debian source format as 3.0 native
[debian/ipip] / route.c
1 /* route.c              Route file reader
2  *
3  * $Id: route.c,v 1.3 1995/03/19 17:21:06 bdale Exp $
4  *
5  * Copyright 1991, Michael Westerhof, Sun Microsystems, Inc.
6  * This software may be freely used, distributed, or modified, providing
7  * this header is not removed.
8  *
9  */
10
11 #include <stdio.h>
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <netdb.h>
15 #include <memory.h>
16 #include <fcntl.h>
17 #include <string.h>
18 #include <ctype.h>
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
21 #include <syslog.h>
22 #include <stdlib.h>
23
24 #include "ipip.h"
25
26 static void rerr();             /* General error printer */
27 static void init_route();
28 static void r_route();
29 static void print_routes();
30 static void sort_routes();
31
32 static int rlineno;
33 static int rerrflag;
34 int rts_top;
35 struct ipip_route rts[MAX_ROUTES];
36
37 /*
38  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
39  * open and read the route file
40  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
41  */
42 int
43 read_routes(f)
44 char *f;
45 {
46         FILE *cf;
47         char buf[256], *p;
48
49         init_route();
50
51 /* Open the route file */
52         if((cf = fopen(f,"r"))==NULL){
53                 (void)fprintf(stderr,"%sRoute file %s not found or could not be opened\n",progname,f);
54                 return -1;
55         }
56
57         while(fgets(buf, 255, cf)!=NULL){
58                 rlineno++;
59                 if((p = strtok(buf, " \t\n\r"))==NULL)continue;
60                 if(*p=='#' || *p==';')continue;
61
62                 if(strcmp(p,"route")==0)r_route();
63 /*              else if(strcmp(p,"whatever")==0)r_dowhatever(); */
64                 else rerr("Unrecognized command: %s",p);
65         }
66
67         if(rts_top==0)rerr("No routes defined","");
68
69         if(debugd)print_routes();
70
71         sort_routes();
72
73         if(debugd)print_routes();
74
75         return rerrflag;
76 }
77 /*
78  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
79  * Initialize defaults and null route entries
80  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
81  */
82 static void
83 init_route()
84 {
85         int i;
86
87         for(i=0;i<MAX_ROUTES;i++){
88                 rts[i].ipaddr = 0;
89                 rts[i].mask = 0xffffffff;
90                 rts[i].destif = NULL;
91                 rts[i].destaddr = 0;
92                 rts[i].destport = 0;
93                 rts[i].hits = 0;
94         }
95         rts_top = 0;
96
97         rlineno = 0;
98         rerrflag = 0;
99 }
100
101 /*
102  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
103  * Print out the route table (DEBUG)
104  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
105  */
106 static void
107 print_routes()
108 {
109         int i, port, type;
110         unsigned char *p, *q;
111         char *id;
112         unsigned int m;
113
114         if(rerrflag==0)(void)syslog(LOG_DEBUG,"%d routes:", rts_top);
115         else (void)syslog(LOG_DEBUG,"%d routes (there are errors):", rts_top);
116         for(i=0;i<rts_top;i++){
117                 p = (unsigned char *)&rts[i].ipaddr;            
118                 q = (unsigned char *)&rts[i].destaddr;          
119                 if(rts[i].destif != NULL){
120                         id = rts[i].destif->id;
121                         type = rts[i].destif->type;
122                 } else {
123                         id = "unknown";
124                         type = IF_TYPE_NONE;
125                 }
126                 port = ntohs(rts[i].destport);
127                 m = ntohl(rts[i].mask);
128
129                 if((type == IF_TYPE_SLIP)||
130                    (type == IF_TYPE_TUN)){
131                         (void)syslog(LOG_DEBUG,"ip %d.%d.%d.%d mask 0x%08x interface %s\n",
132                                 p[0],p[1],p[2],p[3],m,id);
133                 } else if(type == IF_TYPE_IPIP){
134                         (void)syslog(LOG_DEBUG,"ip %d.%d.%d.%d mask 0x%08x interface %s ip %d.%d.%d.%d\n",
135                                 p[0],p[1],p[2],p[3],m,id,
136                                 q[0],q[1],q[2],q[3]);
137                 } else {
138                         (void)syslog(LOG_DEBUG,"ip %d.%d.%d.%d mask 0x%08x interface %s ip %d.%d.%d.%d port %d\n",
139                                 p[0],p[1],p[2],p[3],m,id,
140                                 q[0],q[1],q[2],q[3],port);
141                 }
142         }
143 }
144
145 /*
146  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
147  * Print a general route file error
148  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
149  */
150 static void
151 rerr(s,a)
152 char *s;
153 char *a;
154 {
155         (void)syslog(LOG_ERR,"Route file error at line %d:\n",rlineno);
156         (void)syslog(LOG_ERR,s,a);
157         rerrflag--;
158 }
159
160 /*
161  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
162  * Handle the "route" command
163  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
164  */
165 static void
166 r_route()
167 {
168         int i, syntax;
169         char *q;
170         struct hostent *he;
171
172         if(rts_top>=MAX_ROUTES){
173                 rerr("Too many routes defined","");
174                 return;
175         }
176
177         syntax = 0;
178
179         if((q = strtok((char *)NULL, " \t\n\r"))){
180                 if((he = gethostbyname(q))){
181                         (void)memcpy((char *)&rts[rts_top].ipaddr,
182                                         he->h_addr_list[0], 4);
183                 } else {
184                         if((rts[rts_top].ipaddr = inet_addr(q)) == 0xffffffff)
185                                 rerr("Bad IP address: %s",q);
186                 }
187         } else syntax++;
188
189         if((q = strtok((char *)NULL, " \t\n\r"))){
190                 rts[rts_top].mask = htonl(strtoul(q, NULL, 0));
191         } else syntax++;
192
193         if((q = strtok((char *)NULL, " \t\n\r"))){
194                 for(i=0;i<ifs_top;i++){
195                         if(strcmp(q,ifs[i].id)==0)rts[rts_top].destif = &ifs[i];
196                 }
197                 if(rts[rts_top].destif == NULL)
198                         rerr("Interface %s not defined",q);
199         } else syntax++;
200
201         if((q = strtok((char *)NULL, " \t\n\r"))){
202                 if((he = gethostbyname(q))){
203                         (void)memcpy((char *)&rts[rts_top].destaddr,
204                                         he->h_addr_list[0], 4);
205                 } else {
206                         if((rts[rts_top].destaddr = inet_addr(q)) == (unsigned long)-1)
207                                 rerr("Bad destination IP address: %s",q);
208                 }
209         }
210
211         if((q = strtok((char *)NULL, " \t\n\r"))){
212                 rts[rts_top].destport = htons((unsigned short)atoi(q));
213         }
214
215         if(syntax)rerr("Syntax error (route <ipaddr> <mask> <iface> [<destipaddr> [<destport>]]","");
216
217         rts_top++;
218 }
219
220 static void
221 sort_routes()
222 {
223         struct ipip_route *tmptable ;
224         static unsigned long mask_entries[] = { \
225         0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8,  \
226         0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80,  \
227         0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800,  \
228         0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000,  \
229         0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000,  \
230         0xfff00000, 0xffe00000, 0xffc00000, 0xff800000,  \
231         0xff000000, 0xfe000000, 0xfc000000, 0xf8000000,  \
232         0xf0000000, 0xe0000000, 0xc0000000, 0x80000000,  \
233         0x00000000 } ;
234         int i, j, newrows ;
235
236         tmptable = malloc ( (rts_top+1) * sizeof(struct ipip_route) ) ;
237         
238         if (tmptable == NULL) {
239                 rerr("Unable to allocate memory to resort table","");
240                 return ;
241         }
242
243         /* Search the original table 32 times for each of the 32 possible */
244         /* masks.  Copy the most specific routes to the tmptable first    */
245         newrows = 0;
246         for ( i = 0 ; i <= 32 ; i++ )
247                 for ( j = 0 ; j < rts_top ; j++ )
248                         if (rts[j].mask == htonl(mask_entries[i]))
249                                 tmptable[newrows++] = rts[j];
250
251         /* Copy the tmptable back to original */
252         for ( i = 0 ; i < rts_top ; i++ )
253                 rts[i] = tmptable[i] ;
254         free (tmptable);
255 }