void process_packet(int socket) { unsigned char *buffer; int size = 0; struct sockaddr_in recv_addr; struct iphdr *ipheader; struct ospfhdr *ospfheader; unsigned int iphdr_len, recv_addr_len; struct ospf_interface *oiface; buffer = malloc(sizeof(*buffer)*REPLAY_PACKET_BUFFER); memset(&recv_addr,0,sizeof(recv_addr)); recv_addr_len = sizeof(recv_addr); size = recvfrom(socket, buffer, REPLAY_PACKET_BUFFER, 0, (struct sockaddr *)&recv_addr, &recv_addr_len); if(size>0) { oiface = find_oiface_by_socket(socket); if(recv_addr.sin_addr.s_addr != oiface->iface->ip.s_addr) { ipheader = (struct iphdr *)buffer; iphdr_len = ipheader->ihl*4; ospfheader = (struct ospfhdr *)(buffer+iphdr_len); switch(ospfheader->mesg_type) { case OSPF_MESG_HELLO: process_hello(buffer+iphdr_len,ipheader->saddr,ipheader->daddr,((unsigned int)ntohs(ospfheader->packet_length)),oiface); break; case OSPF_MESG_DBDESC: process_dbdesc(buffer+iphdr_len,ipheader->saddr,ipheader->daddr,((unsigned int)ntohs(ospfheader->packet_length)),oiface); break; case OSPF_MESG_LSR: process_lsr(buffer+iphdr_len,ipheader->saddr,ipheader->daddr,((unsigned int)ntohs(ospfheader->packet_length)),oiface); break; case OSPF_MESG_LSU: process_lsu(buffer+iphdr_len,ipheader->saddr,ipheader->daddr,((unsigned int)ntohs(ospfheader->packet_length)),oiface); break; case OSPF_MESG_LSACK: process_lsack(buffer+iphdr_len,ipheader->saddr,ipheader->daddr,((unsigned int)ntohs(ospfheader->packet_length)),oiface); break; } } } else { //error reading in packet } free(buffer); }
void *recv_loop(void *p) { uint8_t buf[BUFFER_SIZE]; interface *iface; ospf_header *ospfhdr; neighbor *nbr; in_addr_t src; while (*(int *)p) { iface = recv_ospf(sock, buf, BUFFER_SIZE, &src); ospfhdr = (ospf_header *)(buf + sizeof(struct iphdr)); /* check if the packet is from myself */ if (ospfhdr->router_id == myid) continue; for (nbr = iface->nbrs; nbr; nbr = nbr->next) if (ospfhdr->router_id == nbr->router_id) break; switch (ospfhdr->type) { case OSPF_TYPE_HELLO: process_hello(iface, nbr, ospfhdr, src); break; case OSPF_TYPE_DD: process_dd(iface, nbr, ospfhdr); break; case OSPF_TYPE_LSR: process_lsr(nbr, ospfhdr);break; case OSPF_TYPE_LSU: process_lsu(iface->a, nbr, ospfhdr);break; case OSPF_TYPE_LSACK: process_ack(nbr, ospfhdr);break; default: break; } } return NULL; }
/* * Serial interrupt handler */ const struct sigevent * ser_intr(void *area, int id) { int status, cnt; unsigned char msr, lsr; DEV_OMAP *dev = area; struct sigevent *event = NULL; unsigned iir; uintptr_t *port = dev->port; #ifdef PWR_MAN /* Our idle state can be changed by a devctl so we must use a spinlock */ InterruptLock(&dev->idle_spinlock); #endif while (1) { status = 0; #ifdef PWR_MAN if (dev->idle) { omap_clock_enable_isr(dev); #ifdef WINBT omap_force_rts(dev, 0); // once we are in idle mode the only interrupt that can wake us up is from am CTS line change tti(&dev->tty, TTI_OHW_STOP); // start a spare timer for debouncing, if this timer actually // expires, then this was a CTS glitch, if the timer // is cleared by having data on the RX line, it will send up the // oband notification to wake up the host. dev->signal_oband_notification = 1; if( dev->tty.un.s.spare_tmr == 0 ){ atomic_set (&dev->tty.eflags, EVENT_TIMER_QUEUE); dev->tty.un.s.spare_tmr = 4; // queue the event here because the switch statement can just exit // without actually queuing the event with setting the status flag if((dev->tty.flags & EVENT_QUEUED) == 0) { event = &ttyctrl.event; dev_lock(&ttyctrl); ttyctrl.event_queue[ttyctrl.num_events++] = &dev->tty; atomic_set(&dev->tty.flags, EVENT_QUEUED); dev_unlock(&ttyctrl); continue; } } #endif // End of #ifdef WINBT } unsigned ssr = read_omap(port[OMAP_UART_SSR]); if (ssr & OMAP_SSR_WAKEUP_STS) { /* Clear the wake up interrupt */ set_port(port[OMAP_UART_SCR], OMAP_SCR_WAKEUPEN, 0); } #endif iir = read_omap(port[OMAP_UART_IIR]) & OMAP_II_MASK; switch(iir) { case OMAP_II_RX: // Receive data case OMAP_II_RXTO: // Receive data timeout case OMAP_II_LS: // Line status change cnt = 0; lsr = read_omap(port[OMAP_UART_LSR]); do { if( lsr & (OMAP_LSR_BI|OMAP_LSR_OE|OMAP_LSR_FE|OMAP_LSR_PE) ) { // Error character status |= process_lsr(dev, lsr); } else { // Good character status |= tti(&dev->tty, (read_omap(port[OMAP_UART_RHR])) & 0xff); cnt++; } lsr = read_omap(port[OMAP_UART_LSR]); } while(lsr & OMAP_LSR_RXRDY && cnt < FIFO_SIZE); #ifdef WINBT if( cnt && dev->signal_oband_notification ){ // received data after a CTS wake up // notify the host that it's a valid CTS wakeup. dev->signal_oband_notification = 0; dev->tty.oband_data |= _OBAND_SER_MS; atomic_set(&dev->tty.flags, OBAND_DATA); atomic_set(&dev->tty.flags, EVENT_NOTIFY_OBAND); status |= 1; } if (cnt && dev->tty.un.s.spare_tmr) { // received data, clear spare timer dev->tty.un.s.spare_tmr = 0; } #endif break; case OMAP_II_TX: // Transmit buffer empty // disable thr interrupt set_port(dev->port[OMAP_UART_IER], OMAP_IER_THR, 0); dev->tty.un.s.tx_tmr = 0; /* Send event to io-char, tto() will be processed at thread time */ atomic_set(&dev->tty.flags, EVENT_TTO); status |= 1; break; case OMAP_II_MS: // Modem change msr = read_omap(port[OMAP_UART_MSR]); if(msr & OMAP_MSR_DDCD) { status |= tti(&dev->tty, (msr & OMAP_MSR_DCD) ? TTI_CARRIER : TTI_HANGUP); } if((msr & OMAP_MSR_DCTS) && (dev->tty.c_cflag & OHFLOW)) { status |= tti(&dev->tty, (msr & OMAP_MSR_CTS) ? TTI_OHW_CONT : TTI_OHW_STOP); } /* OBAND notification of Modem status change */ dev->tty.oband_data |= _OBAND_SER_MS; atomic_set(&dev->tty.flags, OBAND_DATA); atomic_set(&dev->tty.flags, EVENT_NOTIFY_OBAND); status |= 1; break; case OMAP_II_NOINTR: // No interrupt if (read_omap(port[OMAP_UART_SSR]) & OMAP_SSR_WAKEUP_STS) { // Wake up interrupt set_port(port[OMAP_UART_SCR], OMAP_SCR_WAKEUPEN, 0); // clear wakeup interrupt set_port(port[OMAP_UART_SCR], OMAP_SCR_WAKEUPEN, OMAP_SCR_WAKEUPEN); // re-enable wakeup interrupt } default: goto done; } if (status) { if((dev->tty.flags & EVENT_QUEUED) == 0) { event = &ttyctrl.event; dev_lock(&ttyctrl); ttyctrl.event_queue[ttyctrl.num_events++] = &dev->tty; atomic_set(&dev->tty.flags, EVENT_QUEUED); dev_unlock(&ttyctrl); } } } done: #ifdef PWR_MAN InterruptUnlock(&dev->idle_spinlock); #endif return (event); }