⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tr.c

📁 DHCP服务器源码
💻 C
字号:
/* tr.c   token ring interface support   Contributed in May of 1999 by Andrew Chittenden *//* * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") * Copyright (c) 1996-2003 by Internet Software Consortium * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * *   Internet Systems Consortium, Inc. *   950 Charter Street *   Redwood City, CA 94063 *   <info@isc.org> *   http://www.isc.org/ */#ifndef lintstatic char copyright[] ="$Id: tr.c,v 1.7.2.2 2004/06/10 17:59:21 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";#endif /* not lint */#include "dhcpd.h"#if defined (HAVE_TR_SUPPORT) && \	(defined (PACKET_ASSEMBLY) || defined (PACKET_DECODING))#include "includes/netinet/ip.h"#include "includes/netinet/udp.h"#include "includes/netinet/if_ether.h"#include "netinet/if_tr.h"#include <sys/time.h>/* * token ring device handling subroutines.  These are required as token-ring * does not have a simple on-the-wire header but requires the use of * source routing */static int insert_source_routing PROTO ((struct trh_hdr *trh, struct interface_info* interface));static void save_source_routing PROTO ((struct trh_hdr *trh, struct interface_info* interface));static void expire_routes PROTO ((void));/* * As we keep a list of interesting routing information only, a singly * linked list is all we need */struct routing_entry {        struct routing_entry *next;        unsigned char addr[TR_ALEN];        unsigned char iface[5];        __u16 rcf;                      /* route control field */        __u16 rseg[8];                  /* routing registers */        unsigned long access_time;      /* time we last used this entry */};static struct routing_entry *routing_info = NULL;static int routing_timeout = 10;static struct timeval routing_timer;void assemble_tr_header (interface, buf, bufix, to)	struct interface_info *interface;	unsigned char *buf;	unsigned *bufix;	struct hardware *to;{        struct trh_hdr *trh;        int hdr_len;        struct trllc *llc;        /* set up the token header */        trh = (struct trh_hdr *) &buf[*bufix];        if (interface -> hw_address.hlen - 1 == sizeof (trh->saddr))                memcpy (trh->saddr, &interface -> hw_address.hbuf [1],                                    sizeof (trh->saddr));        else                memset (trh->saddr, 0x00, sizeof (trh->saddr));        if (to && to -> hlen == 7) /* XXX */                memcpy (trh->daddr, &to -> hbuf [1], sizeof trh->daddr);        else                memset (trh->daddr, 0xff, sizeof (trh->daddr));	hdr_len = insert_source_routing (trh, interface);        trh->ac = AC;        trh->fc = LLC_FRAME;        /* set up the llc header for snap encoding after the tr header */        llc = (struct trllc *)(buf + *bufix + hdr_len);        llc->dsap = EXTENDED_SAP;        llc->ssap = EXTENDED_SAP;        llc->llc = UI_CMD;        llc->protid[0] = 0;        llc->protid[1] = 0;        llc->protid[2] = 0;        llc->ethertype = htons(ETHERTYPE_IP);        hdr_len += sizeof(struct trllc);        *bufix += hdr_len;}static unsigned char tr_broadcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };/* * decoding the token header is a bit complex as you can see here. It is * further complicated by the linux kernel stripping off some valuable * information (see comment below) even though we've asked for the raw * packets. */ssize_t decode_tr_header (interface, buf, bufix, from)        struct interface_info *interface;        unsigned char *buf;        unsigned bufix;        struct hardware *from;{        struct trh_hdr *trh = (struct trh_hdr *) buf + bufix;        struct trllc *llc;	struct ip *ip;	struct udphdr *udp;        unsigned int route_len = 0;        ssize_t hdr_len;        struct timeval now;        /* see whether any source routing information has expired */        gettimeofday(&now, NULL);	if (routing_timer.tv_sec == 0)                routing_timer.tv_sec = now.tv_sec + routing_timeout;        else if ((now.tv_sec - routing_timer.tv_sec) > 0)                expire_routes();        /* the kernel might have stripped off the source         * routing bit. We try a heuristic to determine whether         * this is the case and put it back on if so         */        route_len = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8;        llc = (struct trllc *)(buf + bufix + sizeof(struct trh_hdr)-TR_MAXRIFLEN+route_len);        if (llc->dsap == EXTENDED_SAP                        && llc->ssap == EXTENDED_SAP                        && llc->llc == UI_CMD                        && llc->protid[0] == 0                        && llc->protid[1] == 0                        && llc->protid[2] == 0) {                /* say there is source routing information present */                trh->saddr[0] |= TR_RII;	        }	if (trh->saddr[0] & TR_RII)                route_len = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8;        else                route_len = 0;        hdr_len = sizeof (struct trh_hdr) - TR_MAXRIFLEN + route_len;        /* now filter out unwanted packets: this is based on the packet         * filter code in bpf.c */        llc = (struct trllc *)(buf + bufix + hdr_len);        ip = (struct ip *) (llc + 1);        udp = (struct udphdr *) ((unsigned char*) ip + IP_HL (ip));        /* make sure it is a snap encoded, IP, UDP, unfragmented packet sent         * to our port */        if (llc->dsap != EXTENDED_SAP                        || ntohs(llc->ethertype) != ETHERTYPE_IP                        || ip->ip_p != IPPROTO_UDP                        || (ntohs (ip->ip_off) & IP_OFFMASK) != 0                        || udp->uh_dport != local_port)                return -1;        /* only save source routing information for packets from valued hosts */        save_source_routing(trh, interface);        return hdr_len + sizeof (struct trllc);}/* insert_source_routing inserts source route information into the token ring * header */static int insert_source_routing (trh, interface)        struct trh_hdr *trh;        struct interface_info* interface;{	struct routing_entry *rover;        struct timeval now;        unsigned int route_len = 0;        gettimeofday(&now, NULL);	/* single route broadcasts as per rfc 1042 */	if (memcmp(trh->daddr, tr_broadcast,TR_ALEN) == 0) {		trh->saddr[0] |= TR_RII;		trh->rcf = ((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK;                  trh->rcf |= (TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST);		trh->rcf = htons(trh->rcf);	} else {		/* look for a routing entry */                for (rover = routing_info; rover != NULL; rover = rover->next) {                        if (memcmp(rover->addr, trh->daddr, TR_ALEN) == 0)                                break;                }		if (rover != NULL) {                        /* success: route that frame */                        if ((rover->rcf & TR_RCF_LEN_MASK) >> 8) {                                __u16 rcf = rover->rcf;				memcpy(trh->rseg,rover->rseg,sizeof(trh->rseg));				rcf ^= TR_RCF_DIR_BIT;					rcf &= ~TR_RCF_BROADCAST_MASK;                                trh->rcf = htons(rcf);				trh->saddr[0] |= TR_RII;			}			rover->access_time = now.tv_sec;		} else {                        /* we don't have any routing information so send a                         * limited broadcast */                        trh->saddr[0] |= TR_RII;                        trh->rcf = ((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK;                          trh->rcf |= (TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST);                        trh->rcf = htons(trh->rcf);		}	}	/* return how much of the header we've actually used */	if (trh->saddr[0] & TR_RII)                route_len = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8;        else                route_len = 0;        return sizeof (struct trh_hdr) - TR_MAXRIFLEN + route_len;}/* * save any source routing information */static void save_source_routing(trh, interface)        struct trh_hdr *trh;        struct interface_info *interface;{        struct routing_entry *rover;        struct timeval now;        unsigned char saddr[TR_ALEN];        __u16 rcf = 0;        gettimeofday(&now, NULL);        memcpy(saddr, trh->saddr, sizeof(saddr));        saddr[0] &= 0x7f;   /* strip off source routing present flag */        /* scan our table to see if we've got it */        for (rover = routing_info; rover != NULL; rover = rover->next) {                if (memcmp(&rover->addr[0], &saddr[0], TR_ALEN) == 0)                        break;        }        /* found an entry so update it with fresh information */        if (rover != NULL) {                if ((trh->saddr[0] & TR_RII) &&		    ((ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8) > 2) {                        rcf = ntohs(trh->rcf);                        rcf &= ~TR_RCF_BROADCAST_MASK;                        memcpy(rover->rseg, trh->rseg, sizeof(rover->rseg));                }                rover->rcf = rcf;                rover->access_time = now.tv_sec;                return;     /* that's all folks */        }        /* no entry found, so create one */        rover = dmalloc (sizeof (struct routing_entry), MDL);        if (rover == NULL) {                fprintf(stderr,			"%s: unable to save source routing information\n",			__FILE__);                return;        }        memcpy(rover->addr, saddr, sizeof(rover->addr));        memcpy(rover->iface, interface->name, 5);        rover->access_time = now.tv_sec;        if (trh->saddr[0] & TR_RII) {                if (((ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8) > 2) {                        rcf = ntohs(trh->rcf);                        rcf &= ~TR_RCF_BROADCAST_MASK;                        memcpy(rover->rseg, trh->rseg, sizeof(rover->rseg));                }                rover->rcf = rcf;        }        /* insert into list */        rover->next = routing_info;        routing_info = rover;        return;}/* * get rid of old routes */static void expire_routes(){        struct routing_entry *rover;        struct routing_entry **prover = &routing_info;        struct timeval now;        gettimeofday(&now, NULL);        while((rover = *prover) != NULL) {                if ((now.tv_sec - rover->access_time) > routing_timeout) {                        *prover = rover->next;                        dfree (rover, MDL);                } else                        prover = &rover->next;        }        /* Reset the timer */        routing_timer.tv_sec = now.tv_sec + routing_timeout;        routing_timer.tv_usec = now.tv_usec;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -