00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "dhcpd.h"
00031
00032 #if defined (HAVE_TR_SUPPORT) && \
00033 (defined (PACKET_ASSEMBLY) || defined (PACKET_DECODING))
00034 #include "includes/netinet/ip.h"
00035 #include "includes/netinet/udp.h"
00036 #include "includes/netinet/if_ether.h"
00037 #include "netinet/if_tr.h"
00038 #include <sys/time.h>
00039
00040
00041
00042
00043
00044
00045
00046 static int insert_source_routing (struct trh_hdr *trh, struct interface_info* interface);
00047 static void save_source_routing (struct trh_hdr *trh, struct interface_info* interface);
00048 static void expire_routes (void);
00049
00050
00051
00052
00053
00054 struct routing_entry {
00055 struct routing_entry *next;
00056 unsigned char addr[TR_ALEN];
00057 unsigned char iface[5];
00058 u_int16_t rcf;
00059 u_int16_t rseg[8];
00060 unsigned long access_time;
00061 };
00062
00063 static struct routing_entry *routing_info = NULL;
00064
00065 static int routing_timeout = 10;
00066 static struct timeval routing_timer;
00067
00068 void assemble_tr_header (interface, buf, bufix, to)
00069 struct interface_info *interface;
00070 unsigned char *buf;
00071 unsigned *bufix;
00072 struct hardware *to;
00073 {
00074 struct trh_hdr *trh;
00075 int hdr_len;
00076 struct trllc *llc;
00077
00078
00079
00080 trh = (struct trh_hdr *) &buf[*bufix];
00081 if (interface -> hw_address.hlen - 1 == sizeof (trh->saddr))
00082 memcpy (trh->saddr, &interface -> hw_address.hbuf [1],
00083 sizeof (trh->saddr));
00084 else
00085 memset (trh->saddr, 0x00, sizeof (trh->saddr));
00086
00087 if (to && to -> hlen == 7)
00088 memcpy (trh->daddr, &to -> hbuf [1], sizeof trh->daddr);
00089 else
00090 memset (trh->daddr, 0xff, sizeof (trh->daddr));
00091
00092 hdr_len = insert_source_routing (trh, interface);
00093
00094 trh->ac = AC;
00095 trh->fc = LLC_FRAME;
00096
00097
00098 llc = (struct trllc *)(buf + *bufix + hdr_len);
00099 llc->dsap = EXTENDED_SAP;
00100 llc->ssap = EXTENDED_SAP;
00101 llc->llc = UI_CMD;
00102 llc->protid[0] = 0;
00103 llc->protid[1] = 0;
00104 llc->protid[2] = 0;
00105 llc->ethertype = htons(ETHERTYPE_IP);
00106
00107 hdr_len += sizeof(struct trllc);
00108
00109 *bufix += hdr_len;
00110 }
00111
00112
00113 static unsigned char tr_broadcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
00114
00115
00116
00117
00118
00119
00120
00121 ssize_t decode_tr_header (interface, buf, bufix, from)
00122 struct interface_info *interface;
00123 unsigned char *buf;
00124 unsigned bufix;
00125 struct hardware *from;
00126 {
00127 struct trh_hdr *trh = (struct trh_hdr *) buf + bufix;
00128 struct trllc *llc;
00129 struct ip *ip;
00130 struct udphdr *udp;
00131 unsigned int route_len = 0;
00132 ssize_t hdr_len;
00133 struct timeval now;
00134
00135
00136 gettimeofday(&now, NULL);
00137
00138 if (routing_timer.tv_sec == 0)
00139 routing_timer.tv_sec = now.tv_sec + routing_timeout;
00140 else if ((now.tv_sec - routing_timer.tv_sec) > 0)
00141 expire_routes();
00142
00143
00144
00145
00146
00147 route_len = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8;
00148 llc = (struct trllc *)(buf + bufix + sizeof(struct trh_hdr)-TR_MAXRIFLEN+route_len);
00149 if (llc->dsap == EXTENDED_SAP
00150 && llc->ssap == EXTENDED_SAP
00151 && llc->llc == UI_CMD
00152 && llc->protid[0] == 0
00153 && llc->protid[1] == 0
00154 && llc->protid[2] == 0) {
00155
00156 trh->saddr[0] |= TR_RII;
00157 }
00158
00159 if (trh->saddr[0] & TR_RII)
00160 route_len = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8;
00161 else
00162 route_len = 0;
00163
00164 hdr_len = sizeof (struct trh_hdr) - TR_MAXRIFLEN + route_len;
00165
00166
00167
00168 llc = (struct trllc *)(buf + bufix + hdr_len);
00169 ip = (struct ip *) (llc + 1);
00170 udp = (struct udphdr *) ((unsigned char*) ip + IP_HL (ip));
00171
00172
00173
00174 if (llc->dsap != EXTENDED_SAP
00175 || ntohs(llc->ethertype) != ETHERTYPE_IP
00176 || ip->ip_p != IPPROTO_UDP
00177 || (ntohs (ip->ip_off) & IP_OFFMASK) != 0
00178 || udp->uh_dport != local_port)
00179 return -1;
00180
00181
00182 save_source_routing(trh, interface);
00183
00184 return hdr_len + sizeof (struct trllc);
00185 }
00186
00187
00188
00189
00190 static int insert_source_routing (trh, interface)
00191 struct trh_hdr *trh;
00192 struct interface_info* interface;
00193 {
00194 struct routing_entry *rover;
00195 struct timeval now;
00196 unsigned int route_len = 0;
00197
00198 gettimeofday(&now, NULL);
00199
00200
00201 if (memcmp(trh->daddr, tr_broadcast,TR_ALEN) == 0) {
00202 trh->saddr[0] |= TR_RII;
00203 trh->rcf = ((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK;
00204 trh->rcf |= (TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST);
00205 trh->rcf = htons(trh->rcf);
00206 } else {
00207
00208 for (rover = routing_info; rover != NULL; rover = rover->next) {
00209 if (memcmp(rover->addr, trh->daddr, TR_ALEN) == 0)
00210 break;
00211 }
00212
00213 if (rover != NULL) {
00214
00215 if ((rover->rcf & TR_RCF_LEN_MASK) >> 8) {
00216 u_int16_t rcf = rover->rcf;
00217 memcpy(trh->rseg,rover->rseg,sizeof(trh->rseg));
00218 rcf ^= TR_RCF_DIR_BIT;
00219 rcf &= ~TR_RCF_BROADCAST_MASK;
00220 trh->rcf = htons(rcf);
00221 trh->saddr[0] |= TR_RII;
00222 }
00223 rover->access_time = now.tv_sec;
00224 } else {
00225
00226
00227 trh->saddr[0] |= TR_RII;
00228 trh->rcf = ((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK;
00229 trh->rcf |= (TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST);
00230 trh->rcf = htons(trh->rcf);
00231 }
00232 }
00233
00234
00235 if (trh->saddr[0] & TR_RII)
00236 route_len = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8;
00237 else
00238 route_len = 0;
00239
00240 return sizeof (struct trh_hdr) - TR_MAXRIFLEN + route_len;
00241 }
00242
00243
00244
00245
00246 static void save_source_routing(trh, interface)
00247 struct trh_hdr *trh;
00248 struct interface_info *interface;
00249 {
00250 struct routing_entry *rover;
00251 struct timeval now;
00252 unsigned char saddr[TR_ALEN];
00253 u_int16_t rcf = 0;
00254
00255 gettimeofday(&now, NULL);
00256
00257 memcpy(saddr, trh->saddr, sizeof(saddr));
00258 saddr[0] &= 0x7f;
00259
00260
00261 for (rover = routing_info; rover != NULL; rover = rover->next) {
00262 if (memcmp(&rover->addr[0], &saddr[0], TR_ALEN) == 0)
00263 break;
00264 }
00265
00266
00267 if (rover != NULL) {
00268 if ((trh->saddr[0] & TR_RII) &&
00269 ((ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8) > 2) {
00270 rcf = ntohs(trh->rcf);
00271 rcf &= ~TR_RCF_BROADCAST_MASK;
00272 memcpy(rover->rseg, trh->rseg, sizeof(rover->rseg));
00273 }
00274 rover->rcf = rcf;
00275 rover->access_time = now.tv_sec;
00276 return;
00277 }
00278
00279
00280 rover = dmalloc (sizeof (struct routing_entry), MDL);
00281 if (rover == NULL) {
00282 fprintf(stderr,
00283 "%s: unable to save source routing information\n",
00284 __FILE__);
00285 return;
00286 }
00287
00288 memcpy(rover->addr, saddr, sizeof(rover->addr));
00289 memcpy(rover->iface, interface->name, 5);
00290 rover->access_time = now.tv_sec;
00291 if (trh->saddr[0] & TR_RII) {
00292 if (((ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8) > 2) {
00293 rcf = ntohs(trh->rcf);
00294 rcf &= ~TR_RCF_BROADCAST_MASK;
00295 memcpy(rover->rseg, trh->rseg, sizeof(rover->rseg));
00296 }
00297 rover->rcf = rcf;
00298 }
00299
00300
00301 rover->next = routing_info;
00302 routing_info = rover;
00303
00304 return;
00305 }
00306
00307
00308
00309
00310 static void expire_routes()
00311 {
00312 struct routing_entry *rover;
00313 struct routing_entry **prover = &routing_info;
00314 struct timeval now;
00315
00316 gettimeofday(&now, NULL);
00317
00318 while((rover = *prover) != NULL) {
00319 if ((now.tv_sec - rover->access_time) > routing_timeout) {
00320 *prover = rover->next;
00321 dfree (rover, MDL);
00322 } else
00323 prover = &rover->next;
00324 }
00325
00326
00327 routing_timer.tv_sec = now.tv_sec + routing_timeout;
00328 routing_timer.tv_usec = now.tv_usec;
00329 }
00330
00331 #endif