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