📄 sdla_chdlc.c
字号:
printk(KERN_WARNING " format A.B.C.1 or A.B.C.2.\n"); } */ } return chdlc_configure(card, &cfg);}/*============================================================================ * Process global exception condition */static int process_global_exception(sdla_t *card){ CHDLC_MAILBOX_STRUCT* mbox = card->mbox; int err; mbox->buffer_length = 0; mbox->command = READ_GLOBAL_EXCEPTION_CONDITION; err = sdla_exec(mbox) ? mbox->return_code : CMD_TIMEOUT; if(err != CMD_TIMEOUT ){ switch(mbox->return_code) { case EXCEP_MODEM_STATUS_CHANGE: printk(KERN_INFO "%s: Modem status change\n", card->devname); switch(mbox->data[0] & (DCD_HIGH | CTS_HIGH)) { case (DCD_HIGH): printk(KERN_INFO "%s: DCD high, CTS low\n",card->devname); break; case (CTS_HIGH): printk(KERN_INFO "%s: DCD low, CTS high\n",card->devname); break; case ((DCD_HIGH | CTS_HIGH)): printk(KERN_INFO "%s: DCD high, CTS high\n",card->devname); break; default: printk(KERN_INFO "%s: DCD low, CTS low\n",card->devname); break; } break; case EXCEP_TRC_DISABLED: printk(KERN_INFO "%s: Line trace disabled\n", card->devname); break; case EXCEP_IRQ_TIMEOUT: printk(KERN_INFO "%s: IRQ timeout occurred\n", card->devname); break; default: printk(KERN_INFO "%s: Global exception %x\n", card->devname, mbox->return_code); break; } } return 0;}/*============================================================================ * Process chdlc exception condition */static int process_chdlc_exception(sdla_t *card){ CHDLC_MAILBOX_STRUCT* mb = card->mbox; int err; mb->buffer_length = 0; mb->command = READ_CHDLC_EXCEPTION_CONDITION; err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; if(err != CMD_TIMEOUT) { switch (err) { case EXCEP_LINK_ACTIVE: port_set_state(card, WAN_CONNECTED); break; case EXCEP_LINK_INACTIVE_MODEM: port_set_state(card, WAN_DISCONNECTED); unconfigure_ip(card); break; case EXCEP_LINK_INACTIVE_KPALV: port_set_state(card, WAN_DISCONNECTED); printk(KERN_INFO "%s: Keepalive timer expired.\n", card->devname); unconfigure_ip(card); break; case EXCEP_IP_ADDRESS_DISCOVERED: if (configure_ip(card)) return -1; break; case EXCEP_LOOPBACK_CONDITION: printk(KERN_INFO "%s: Loopback Condition Detected.\n", card->devname); break; case NO_CHDLC_EXCEP_COND_TO_REPORT: printk(KERN_INFO "%s: No exceptions reported.\n", card->devname); break; } } return 0;}/*============================================================================ * Configure IP from SLARP negotiation * This adds dynamic routes when SLARP has provided valid addresses */static int configure_ip (sdla_t* card){ struct net_device *dev = card->wandev.dev; chdlc_private_area_t *chdlc_priv_area = dev->priv; char err; /* set to discover */ if(card->u.c.slarp_timer != 0x00) { CHDLC_MAILBOX_STRUCT* mb = card->mbox; CHDLC_CONFIGURATION_STRUCT *cfg; mb->buffer_length = 0; mb->command = READ_CHDLC_CONFIGURATION; err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; if(err != COMMAND_OK) { chdlc_error(card,err,mb); return -1; } cfg = (CHDLC_CONFIGURATION_STRUCT *)mb->data; chdlc_priv_area->IP_address = cfg->IP_address; chdlc_priv_area->IP_netmask = cfg->IP_netmask; } /* Set flag to add route */ chdlc_priv_area->route_status = ADD_ROUTE; /* The idea here is to add the route in the poll routine. This way, we aren't in interrupt context when adding routes */ card->poll = process_route; return 0;}/*============================================================================ * Un-Configure IP negotiated by SLARP * This removes dynamic routes when the link becomes inactive. */static int unconfigure_ip (sdla_t* card){ struct net_device *dev = card->wandev.dev; chdlc_private_area_t *chdlc_priv_area= dev->priv; if (chdlc_priv_area->route_status == ROUTE_ADDED) { chdlc_priv_area->route_status = REMOVE_ROUTE; /* The idea here is to delete the route in * the poll routine. * This way, we aren't in interrupt context * when adding routes */ card->poll = process_route; } return 0;}/*============================================================================ * Routine to add/remove routes * Called like a polling routine when Routes are flagged to be added/removed. */static void process_route (sdla_t *card){ struct net_device *dev = card->wandev.dev; unsigned char port_num; chdlc_private_area_t *chdlc_priv_area = NULL; u32 local_IP_addr = 0; u32 remote_IP_addr = 0; u32 IP_netmask, IP_addr; int err = 0;#ifdef LINUX_2_1 struct in_device *in_dev; mm_segment_t fs; struct ifreq if_info; struct sockaddr_in *if_data1, *if_data2;#else unsigned long fs = 0; struct rtentry route;#endif chdlc_priv_area = dev->priv; port_num = card->u.c.comm_port; if((chdlc_priv_area->route_status == ADD_ROUTE) && ((chdlc_priv_area->IP_address & 0x000000FF) > 2)) { printk(KERN_INFO "%s: Dynamic route failure.\n",card->devname); if(card->u.c.slarp_timer) { printk(KERN_INFO "%s: Bad IP address %s received\n", card->devname, in_ntoa(ntohl(chdlc_priv_area->IP_address))); printk(KERN_INFO "%s: from remote station.\n", card->devname); }else{ printk(KERN_INFO "%s: Bad IP address %s issued\n", card->devname, in_ntoa(ntohl(chdlc_priv_area->IP_address))); printk(KERN_INFO "%s: to remote station. Local\n", card->devname); printk(KERN_INFO "%s: IP address must be A.B.C.1\n", card->devname); printk(KERN_INFO "%s: or A.B.C.2.\n",card->devname); } /* remove the route due to the IP address error condition */ chdlc_priv_area->route_status = REMOVE_ROUTE; err = 1; } /* If we are removing a route with bad IP addressing, then use the */ /* locally configured IP addresses */ if((chdlc_priv_area->route_status == REMOVE_ROUTE) && err) { /* do not remove a bad route that has already been removed */ if(chdlc_priv_area->route_removed) { card->poll = NULL; return; }#ifdef LINUX_2_1 in_dev = dev->ip_ptr; if(in_dev != NULL) { struct in_ifaddr *ifa = in_dev->ifa_list; if (ifa != NULL ) { local_IP_addr = ifa->ifa_local; IP_netmask = ifa->ifa_mask; } }#else local_IP_addr = dev->pa_addr; remote_IP_addr = dev->pa_dstaddr; IP_netmask = dev->pa_mask;#endif }else{ /* According to Cisco HDLC, if the point-to-point address is A.B.C.1, then we are the opposite (A.B.C.2), and vice-versa. */ IP_netmask = ntohl(chdlc_priv_area->IP_netmask); remote_IP_addr = ntohl(chdlc_priv_area->IP_address); local_IP_addr = (remote_IP_addr & ntohl(0xFFFFFF00)) + (~remote_IP_addr & ntohl(0x0003)); if(!card->u.c.slarp_timer) { IP_addr = local_IP_addr; local_IP_addr = remote_IP_addr; remote_IP_addr = IP_addr; } } fs = get_fs(); /* Save file system */ set_fs(get_ds()); /* Get user space block */#ifdef LINUX_2_1 /* Setup a structure for adding/removing routes */ memset(&if_info, 0, sizeof(if_info)); strcpy(if_info.ifr_name, dev->name);#else /* Setup a structure for adding/removing routes */ dev->pa_mask = IP_netmask; dev->pa_dstaddr = remote_IP_addr; dev->pa_addr = local_IP_addr; memset(&route, 0, sizeof(route)); route.rt_dev = dev->name; route.rt_flags = 0; ((struct sockaddr_in *)&(route.rt_dst))->sin_addr.s_addr = dev->pa_dstaddr; ((struct sockaddr_in *)&(route.rt_dst))->sin_family = AF_INET; ((struct sockaddr_in *)&(route.rt_genmask))->sin_addr.s_addr = 0xFFFFFFFF; ((struct sockaddr_in *)&(route.rt_genmask))->sin_family = AF_INET;#endif switch (chdlc_priv_area->route_status) { case ADD_ROUTE: if(!card->u.c.slarp_timer) {#ifdef LINUX_2_1 if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr; if_data2->sin_addr.s_addr = remote_IP_addr; if_data2->sin_family = AF_INET; err = devinet_ioctl(SIOCSIFDSTADDR, &if_info);#else err = ip_rt_new(&route);#endif } else { #ifdef LINUX_2_1 if_data1 = (struct sockaddr_in *)&if_info.ifr_addr; if_data1->sin_addr.s_addr = local_IP_addr; if_data1->sin_family = AF_INET; if(!(err = devinet_ioctl(SIOCSIFADDR, &if_info))){ if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr; if_data2->sin_addr.s_addr = remote_IP_addr; if_data2->sin_family = AF_INET; err = devinet_ioctl(SIOCSIFDSTADDR, &if_info); }#else err = ip_rt_new(&route);#endif } if(err) { printk(KERN_INFO "%s: Add route %s failed (%d)\n", card->devname, in_ntoa(remote_IP_addr), err); } else { ((chdlc_private_area_t *)dev->priv)->route_status = ROUTE_ADDED; printk(KERN_INFO "%s: Dynamic route added.\n", card->devname); printk(KERN_INFO "%s: Local IP addr : %s\n", card->devname, in_ntoa(local_IP_addr)); printk(KERN_INFO "%s: Remote IP addr: %s\n", card->devname, in_ntoa(remote_IP_addr)); chdlc_priv_area->route_removed = 0; } break; case REMOVE_ROUTE: #ifdef LINUX_2_1 /* Change the local ip address of the interface to 0. * This will also delete the destination route. */ if(!card->u.c.slarp_timer) { if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr; if_data2->sin_addr.s_addr = 0; if_data2->sin_family = AF_INET; err = devinet_ioctl(SIOCSIFDSTADDR, &if_info); } else { if_data1 = (struct sockaddr_in *)&if_info.ifr_addr; if_data1->sin_addr.s_addr = 0; if_data1->sin_family = AF_INET; err = devinet_ioctl(SIOCSIFADDR,&if_info); }#else /* set the point-to-point IP address to 0.0.0.0 */ dev->pa_dstaddr = 0; err = ip_rt_kill(&route);#endif if(err) { printk(KERN_INFO "%s: Remove route %s failed, (err %d)\n", card->devname, in_ntoa(remote_IP_addr), err); } else { ((chdlc_private_area_t *)dev->priv)->route_status = NO_ROUTE; printk(KERN_INFO "%s: Dynamic route removed: %s\n", card->devname, in_ntoa(local_IP_addr)); chdlc_priv_area->route_removed = 1; } break; } set_fs(fs); /* Restore file system */ /* Once we've processed the route, stop polling */ card->poll = NULL;}/*============================================================================= * Store a UDP management packet for later processing. */static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card, struct sk_buff *skb, struct net_device* dev, chdlc_private_area_t* chdlc_priv_area ){ int udp_pkt_stored = 0; if(!chdlc_priv_area->udp_pkt_lgth && (skb->len <= MAX_LGTH_UDP_MGNT_PKT)) { chdlc_priv_area->udp_pkt_lgth = skb->len; chdlc_priv_area->udp_pkt_src = udp_pkt_src; memcpy(chdlc_priv_area->udp_pkt_data, skb->data, skb->len); chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UDP; udp_pkt_stored = 1; }#ifdef LINUX_2_1 dev_kfree_skb(skb);#else if(udp_pkt_src == UDP_PKT_FRM_STACK) dev_kfree_skb(skb, FREE_WRITE); else dev_kfree_skb(skb, FREE_READ);#endif return(udp_pkt_stored);}/*============================================================================= * Process UDP management packet. */static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev, chdlc_private_area_t* chdlc_priv_area ) { unsigned char *buf; unsigned int frames, len; struct sk_buff *new_skb; unsigned short buffer_length, real_len; unsigned long data_ptr; unsigned data_length; int udp_mgmt_req_valid = 1; CHDLC_MAILBOX_STRUCT *mb = card->mbox; SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; chdlc_udp_pkt_t *chdlc_udp_pkt; struct timeval tv; int err; char ut_char; chdlc_udp_pkt = (chdlc_udp_pkt_t *) chdlc_priv_area->udp_pkt_data; switch(chdlc_udp_pkt->cblock.command
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -