📄 sdla_ppp.c
字号:
/* If we get here, some higher layer thinks we've missed an * tx-done interrupt. */ printk(KERN_INFO "%s: interface %s got kicked!\n", card->devname, dev->name); ++ppp_priv_area->if_send_stat.if_send_skb_null; netif_wake_queue(dev); return 0; } sendpacket = skb->data; udp_type = udp_pkt_type( skb, card ); if (udp_type == UDP_PTPIPE_TYPE){ if(store_udp_mgmt_pkt(UDP_PKT_FRM_STACK, card, skb, dev, ppp_priv_area)){ flags->imask |= PPP_INTR_TIMER; } ++ppp_priv_area->if_send_stat.if_send_PIPE_request; netif_start_queue(dev); return 0; } /* Check for broadcast and multicast addresses * If found, drop (deallocate) a packet and return. */ if(chk_bcast_mcast_addr(card, dev, skb)){ ++card->wandev.stats.tx_dropped; dev_kfree_skb_any(skb); netif_start_queue(dev); return 0; } if(card->hw.type != SDLA_S514){ s508_lock(card,&smp_flags); } if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)) { printk(KERN_INFO "%s: Critical in if_send: %lx\n", card->wandev.name,card->wandev.critical); ++card->wandev.stats.tx_dropped; ++ppp_priv_area->if_send_stat.if_send_critical_non_ISR; netif_start_queue(dev); goto if_send_exit_crit; } if (card->wandev.state != WAN_CONNECTED) { ++ppp_priv_area->if_send_stat.if_send_wan_disconnected; ++card->wandev.stats.tx_dropped; netif_start_queue(dev); } else if (!skb->protocol) { ++ppp_priv_area->if_send_stat.if_send_protocol_error; ++card->wandev.stats.tx_errors; netif_start_queue(dev); } else { /*If it's IPX change the network numbers to 0 if they're ours.*/ if( skb->protocol == htons(ETH_P_IPX) ) { if(ppp_priv_area->enable_IPX) { switch_net_numbers( skb->data, ppp_priv_area->network_number, 0); } else { ++card->wandev.stats.tx_dropped; netif_start_queue(dev); goto if_send_exit_crit; } } if (ppp_send(card, skb->data, skb->len, skb->protocol)) { netif_stop_queue(dev); ++ppp_priv_area->if_send_stat.if_send_adptr_bfrs_full; ++ppp_priv_area->if_send_stat.if_send_tx_int_enabled; } else { ++ppp_priv_area->if_send_stat.if_send_bfr_passed_to_adptr; ++card->wandev.stats.tx_packets; card->wandev.stats.tx_bytes += skb->len; netif_start_queue(dev); dev->trans_start = jiffies; } } if_send_exit_crit: if (!(err=netif_queue_stopped(dev))){ dev_kfree_skb_any(skb); }else{ ppp_priv_area->tick_counter = jiffies; flags->imask |= PPP_INTR_TXRDY; /* unmask Tx interrupts */ } clear_bit(SEND_CRIT,&card->wandev.critical); if(card->hw.type != SDLA_S514){ s508_unlock(card,&smp_flags); } return err;}/*============================================================================= * 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, ppp_private_area_t* ppp_priv_area ){ int udp_pkt_stored = 0; if(!ppp_priv_area->udp_pkt_lgth && (skb->len<=MAX_LGTH_UDP_MGNT_PKT)){ ppp_priv_area->udp_pkt_lgth = skb->len; ppp_priv_area->udp_pkt_src = udp_pkt_src; memcpy(ppp_priv_area->udp_pkt_data, skb->data, skb->len); ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_UDP; ppp_priv_area->protocol = skb->protocol; udp_pkt_stored = 1; }else{ if (skb->len > MAX_LGTH_UDP_MGNT_PKT){ printk(KERN_INFO "%s: PIPEMON UDP request too long : %i\n", card->devname, skb->len); }else{ printk(KERN_INFO "%s: PIPEMON UPD request already pending\n", card->devname); } ppp_priv_area->udp_pkt_lgth = 0; } if(udp_pkt_src == UDP_PKT_FRM_STACK){ dev_kfree_skb_any(skb); }else{ dev_kfree_skb_any(skb); } return(udp_pkt_stored);}/*============================================================================ * Reply to UDP Management system. * Return length of reply. */static int reply_udp( unsigned char *data, unsigned int mbox_len ) { unsigned short len, udp_length, temp, ip_length; unsigned long ip_temp; int even_bound = 0; ppp_udp_pkt_t *p_udp_pkt = (ppp_udp_pkt_t *)data; /* Set length of packet */ len = sizeof(ip_pkt_t)+ sizeof(udp_pkt_t)+ sizeof(wp_mgmt_t)+ sizeof(cblock_t)+ mbox_len; /* fill in UDP reply */ p_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY; /* fill in UDP length */ udp_length = sizeof(udp_pkt_t)+ sizeof(wp_mgmt_t)+ sizeof(cblock_t)+ mbox_len; /* put it on an even boundary */ if ( udp_length & 0x0001 ) { udp_length += 1; len += 1; even_bound=1; } temp = (udp_length<<8)|(udp_length>>8); p_udp_pkt->udp_pkt.udp_length = temp; /* swap UDP ports */ temp = p_udp_pkt->udp_pkt.udp_src_port; p_udp_pkt->udp_pkt.udp_src_port = p_udp_pkt->udp_pkt.udp_dst_port; p_udp_pkt->udp_pkt.udp_dst_port = temp; /* add UDP pseudo header */ temp = 0x1100; *((unsigned short *)(p_udp_pkt->data+mbox_len+even_bound)) = temp; temp = (udp_length<<8)|(udp_length>>8); *((unsigned short *)(p_udp_pkt->data+mbox_len+even_bound+2)) = temp; /* calculate UDP checksum */ p_udp_pkt->udp_pkt.udp_checksum = 0; p_udp_pkt->udp_pkt.udp_checksum = calc_checksum(&data[UDP_OFFSET],udp_length+UDP_OFFSET); /* fill in IP length */ ip_length = udp_length + sizeof(ip_pkt_t); temp = (ip_length<<8)|(ip_length>>8); p_udp_pkt->ip_pkt.total_length = temp; /* swap IP addresses */ ip_temp = p_udp_pkt->ip_pkt.ip_src_address; p_udp_pkt->ip_pkt.ip_src_address = p_udp_pkt->ip_pkt.ip_dst_address; p_udp_pkt->ip_pkt.ip_dst_address = ip_temp; /* fill in IP checksum */ p_udp_pkt->ip_pkt.hdr_checksum = 0; p_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data,sizeof(ip_pkt_t)); return len;} /* reply_udp */unsigned short calc_checksum (char *data, int len){ unsigned short temp; unsigned long sum=0; int i; for( i = 0; i <len; i+=2 ) { memcpy(&temp,&data[i],2); sum += (unsigned long)temp; } while (sum >> 16 ) { sum = (sum & 0xffffUL) + (sum >> 16); } temp = (unsigned short)sum; temp = ~temp; if( temp == 0 ) temp = 0xffff; return temp; }/* If incoming is 0 (outgoing)- if the net numbers is ours make it 0 if incoming is 1 - if the net number is 0 make it ours */static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, unsigned char incoming){ unsigned long pnetwork_number; pnetwork_number = (unsigned long)((sendpacket[6] << 24) + (sendpacket[7] << 16) + (sendpacket[8] << 8) + sendpacket[9]); if (!incoming) { //If the destination network number is ours, make it 0 if( pnetwork_number == network_number) { sendpacket[6] = sendpacket[7] = sendpacket[8] = sendpacket[9] = 0x00; } } else { //If the incoming network is 0, make it ours if( pnetwork_number == 0) { sendpacket[6] = (unsigned char)(network_number >> 24); sendpacket[7] = (unsigned char)((network_number & 0x00FF0000) >> 16); sendpacket[8] = (unsigned char)((network_number & 0x0000FF00) >> 8); sendpacket[9] = (unsigned char)(network_number & 0x000000FF); } } pnetwork_number = (unsigned long)((sendpacket[18] << 24) + (sendpacket[19] << 16) + (sendpacket[20] << 8) + sendpacket[21]); if( !incoming ) { //If the source network is ours, make it 0 if( pnetwork_number == network_number) { sendpacket[18] = sendpacket[19] = sendpacket[20] = sendpacket[21] = 0x00; } } else { //If the source network is 0, make it ours if( pnetwork_number == 0 ) { sendpacket[18] = (unsigned char)(network_number >> 24); sendpacket[19] = (unsigned char)((network_number & 0x00FF0000) >> 16); sendpacket[20] = (unsigned char)((network_number & 0x0000FF00) >> 8); sendpacket[21] = (unsigned char)(network_number & 0x000000FF); } }} /* switch_net_numbers *//*============================================================================ * Get ethernet-style interface statistics. * Return a pointer to struct net_device_stats. */static struct net_device_stats *if_stats(struct net_device *dev){ ppp_private_area_t *ppp_priv_area = dev->priv; sdla_t* card; if( ppp_priv_area == NULL ) return NULL; card = ppp_priv_area->card; return &card->wandev.stats;}/****** PPP Firmware Interface Functions ************************************//*============================================================================ * Read firmware code version. * Put code version as ASCII string in str. */static int ppp_read_version(sdla_t *card, char *str){ ppp_mbox_t *mb = card->mbox; int err; memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); mb->cmd.command = PPP_READ_CODE_VERSION; err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; if (err != CMD_OK) ppp_error(card, err, mb); else if (str) { int len = mb->cmd.length; memcpy(str, mb->data, len); str[len] = '\0'; } return err;}/*=========================================================================== * Set Out-Bound Authentication.*/static int ppp_set_outbnd_auth (sdla_t *card, ppp_private_area_t *ppp_priv_area){ ppp_mbox_t *mb = card->mbox; int err; memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); memset(&mb->data, 0, (strlen(ppp_priv_area->userid) + strlen(ppp_priv_area->passwd) + 2 ) ); memcpy(mb->data, ppp_priv_area->userid, strlen(ppp_priv_area->userid)); memcpy((mb->data + strlen(ppp_priv_area->userid) + 1), ppp_priv_area->passwd, strlen(ppp_priv_area->passwd)); mb->cmd.length = strlen(ppp_priv_area->userid) + strlen(ppp_priv_area->passwd) + 2 ; mb->cmd.command = PPP_SET_OUTBOUND_AUTH; err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; if (err != CMD_OK) ppp_error(card, err, mb); return err;}/*=========================================================================== * Set In-Bound Authentication.*/static int ppp_set_inbnd_auth (sdla_t *card, ppp_private_area_t *ppp_priv_area){ ppp_mbox_t *mb = card->mbox; int err, i; char* user_tokens[32]; char* pass_tokens[32]; int userids, passwds; int add_ptr; memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); memset(&mb->data, 0, 1008); memcpy(mb->data, ppp_priv_area->sysname, strlen(ppp_priv_area->sysname)); /* Parse the userid string and the password string and build a string to copy it to the data area of the command structure. The string will look like "SYS_NAME<NULL>USER1<NULL>PASS1<NULL>USER2<NULL>PASS2 ....<NULL> " */ userids = tokenize( ppp_priv_area->userid, user_tokens); passwds = tokenize( ppp_priv_area->passwd, pass_tokens); if (userids != passwds){ printk(KERN_INFO "%s: Number of passwords does not equal the number of user ids\n", card->devname); return 1; } add_ptr = strlen(ppp_priv_area->sysname) + 1; for (i=0; i<userids; i++){ memcpy((mb->data + add_ptr), user_tokens[i], strlen(user_tokens[i])); memcpy((mb->data + add_ptr + strlen(user_tokens[i]) + 1), pass_tokens[i], strlen(pass_tokens[i])); add_ptr = add_ptr + strlen(user_tokens[i]) + 1 + strlen(pass_tokens[i]) + 1; } mb->cmd.length = add_ptr + 1; mb->cmd.command = PPP_SET_INBOUND_AUTH; err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; if (err != CMD_OK) ppp_error(card, err, mb); return err;}/*============================================================================ * Tokenize string. * Parse a string of the following syntax: * <arg1>,<arg2>,... * and fill array of tokens with pointers to string elements. * */static int tokenize (char *str, char **tokens){ int cnt = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -