void *ip232_thread(void *arg) { modem_config *cfg = (modem_config *) arg; int accept_pending = FALSE; int rc; int res = 0; char buf[256]; fd_set readfs; int max_fd = 0; int cSocket; LOG_ENTER(); for (;;) { FD_ZERO(&readfs); FD_SET(cfg->dce_data.dp[1][0], &readfs); max_fd = cfg->dce_data.dp[1][0]; if (accept_pending == FALSE) { FD_SET(cfg->dce_data.sSocket, &readfs); max_fd = MAX(max_fd, cfg->dce_data.sSocket); } LOG(LOG_ALL, "Waiting for incoming ip232 connections"); rc = select(max_fd + 1, &readfs, NULL, NULL, NULL); if (rc < 0) { // handle error } else { if (FD_ISSET(cfg->dce_data.dp[1][0], &readfs)) { // pipe res = read(cfg->dce_data.dp[1][0], buf, sizeof(buf) - 1); LOG(LOG_DEBUG, "ip232 thread notified"); accept_pending = FALSE; } if (FD_ISSET(cfg->dce_data.sSocket, &readfs)) { // ip connection if (cfg->dce_data.ip232_is_connected) { LOG(LOG_DEBUG, "Already have ip232 connection, rejecting new"); // already have a connection... accept and close cSocket = ip_accept(cfg->dce_data.sSocket); if (cSocket > -1) { close(cSocket); } } else { LOG(LOG_DEBUG, "Incoming ip232 connection"); writePipe(cfg->dce_data.dp[0][1], MSG_ACCEPT); accept_pending = TRUE; } } } } LOG_EXIT(); }
// accept lower layer protocol frame // submit to the upper layer protocol void eth_accept(u8* dat, u32 plen) { eth_frm* eth=(eth_frm*)dat; plen-=ETH_HDRLEN; switch(htons(eth->type)) { case ETH_TYPE_ARP: arp_accept(eth->data, plen); break; case ETH_TYPE_IP: ip_accept(eth->data, plen); break; } }
static void physical_ready(CnetEvent ev, CnetTimerID timer, CnetData data) { int link = 1; size_t length; char packet[MAX_MESSAGE_SIZE]; CHECK(CNET_read_physical(&link, packet, &length)); EthernetHeader *header = (EthernetHeader *) packet; if (!packet_is_for_this_node(header)) return; switch (header->type) { case ETHERTYPE_IP: ip_accept(packet + ETHERNET_HEADER_SIZE, length - ETHERNET_HEADER_SIZE); break; case ETHERTYPE_ARP: fprintf(stderr, "WHOOPS! Looks like you haven't handled ARP packets yet :)\n"); break; default: fprintf(stderr, "Unknown Ethernet packet type: %u\n", header->type); } }
int main(int argc, char *argv[]) { modem_config cfg[64]; int modem_count; int port=0; char *ip_addr = NULL; /* gwb */ unsigned char all_busy[255]; pthread_t thread_id; int i; int rc; int sSocket = 0; fd_set readfs; int max_fd=0; int accept_pending=FALSE; int res=0; unsigned char buf[255]; int cSocket; log_init(); LOG_ENTER(); log_set_level(LOG_FATAL); mdm_init(); pb_init(); signal(SIGIO,SIG_IGN); /* Some Linux variant term on SIGIO by default */ modem_count = init(argc, argv, cfg, 64, &ip_addr, &port,all_busy,sizeof(all_busy)); /* gwb */ sSocket = ip_init_server_conn(ip_addr, port); for(i=0;i<modem_count;i++) { if( -1 == pipe(cfg[i].data.mp[0])) { ELOG(LOG_FATAL,"Bridge task incoming IPC pipe could not be created"); exit(-1); } if( -1 == pipe(cfg[i].data.mp[1])) { ELOG(LOG_FATAL,"Bridge task outgoing IPC pipe could not be created"); exit(-1); } if(dce_init_conn(&cfg[i]) < 0) { LOG(LOG_FATAL,"Could not open serial port %s",cfg->dce_data.tty); exit(-1); } cfg[i].line_data.sfd=sSocket; rc=pthread_create(&thread_id,NULL,*run_bridge,(void *)&cfg[i]); if(rc < 0) { ELOG(LOG_FATAL,"IP thread could not be started"); exit(-1); } } for(;;) { FD_ZERO(&readfs); max_fd=0; for(i=0;i<modem_count;i++) { FD_SET(cfg[i].data.mp[0][0], &readfs); max_fd=MAX(max_fd,cfg[i].data.mp[0][0]); } if(accept_pending==FALSE) { max_fd=MAX(max_fd,sSocket); FD_SET(sSocket, &readfs); } LOG(LOG_ALL,"Waiting for incoming connections and/or indicators"); select(max_fd+1, &readfs, NULL, NULL, NULL); for(i=0;i<modem_count;i++) { if (FD_ISSET(cfg[i].data.mp[0][0],&readfs)) { // child pipe res = read(cfg[i].data.mp[0][0],buf,sizeof(buf) -1); if(res > -1) { buf[res]=0; LOG(LOG_DEBUG,"modem core #%d sent response '%c'",i,buf[0]); accept_pending=FALSE; } } } if (FD_ISSET(sSocket,&readfs)) { // IP traffic if(!accept_pending) { LOG(LOG_DEBUG,"Incoming connection pending"); // first try for a modem that is listening. for(i=0;i<modem_count;i++) { if(cfg[i].s[0] != 0 && cfg[i].off_hook == FALSE) { // send signal to pipe saying pick up... LOG(LOG_DEBUG,"Sending incoming connection to listening modem #%d",i); writePipe(cfg[i].data.mp[1][1],MSG_ACCEPT); accept_pending=TRUE; break; } } // now, send to any non-active modem. for(i=0;i<modem_count;i++) { if(cfg[i].off_hook== FALSE) { // send signal to pipe saying pick up... LOG(LOG_DEBUG,"Sending incoming connection to non-connected modem #%d",i); writePipe(cfg[i].data.mp[1][1],MSG_ACCEPT); accept_pending=TRUE; break; } } if(i==modem_count) { LOG(LOG_DEBUG,"No open modem to send to, send notice and close"); // no connections.., accept and print error cSocket=ip_accept(sSocket); if(cSocket > -1) { if(strlen(all_busy) < 1) { ip_write(cSocket,(unsigned char*)MDM_BUSY,strlen(MDM_BUSY)); } else { writeFile(all_busy,cSocket); } close(cSocket); } } } } } LOG_EXIT(); return rc; }
int ip232_read(modem_config *cfg, char *data, int len) { int res; int rc; char buf[256]; int i = 0; int ch; int text_len = 0; LOG_ENTER(); if (len > sizeof(buf)) { LOG(LOG_FATAL, "ip232_read: len > sizeof(buf)"); exit(-1); } if (cfg->dce_data.ip232_is_connected) { res = recv(cfg->dce_data.fd, buf, len, 0); if (0 >= res) { LOG(LOG_INFO, "No ip232 socket data read, assume closed peer"); ip_disconnect(cfg->dce_data.fd); cfg->dce_data.fd = cfg->dce_data.dp[0][0]; cfg->dce_data.ip232_is_connected = FALSE; } else { LOG(LOG_DEBUG, "Read %d bytes from ip232 socket", res); log_trace(TRACE_MODEM_IN, buf, res); while (i < res) { ch = buf[i]; if (cfg->dce_data.ip232_iac) { cfg->dce_data.ip232_iac = FALSE; switch (ch) { case 0: cfg->dce_data.ip232_dtr = FALSE; break; case 1: cfg->dce_data.ip232_dtr = TRUE; break; case 255: data[text_len++] = 255; break; } } else { if (255 == ch) { cfg->dce_data.ip232_iac = TRUE; } else { data[text_len++] = ch; } } i++; } } } else { // not connected res = read(cfg->dce_data.dp[0][0], buf, sizeof(buf)); switch (buf[0]) { case MSG_ACCEPT: // accept connection. LOG(LOG_INFO, "Accepting ip232 connection..."); rc = ip_accept(cfg->dce_data.sSocket); if (res > -1) { cfg->dce_data.fd = rc; cfg->dce_data.ip232_is_connected = TRUE; cfg->dce_data.ip232_dtr = FALSE; cfg->dce_data.ip232_dcd = FALSE; writePipe(cfg->dce_data.dp[1][1], MSG_ACCEPTED); } break; } } LOG_EXIT(); return text_len; }