/* Handle all the messages coming from wily. */ void domsg(Msg *m) { switch(m->mtype) { case 'R': handleread(m); break; default: /* ignore whatever we don't specifically handle */ if(debug) { printf("message received and ignored: "); msg_print(m); } break; } }
static void idle(struct net_device *dev) { unsigned long flags; int state; /* FIXME This is initialized to shut the warning up, but I need to * think this through again. */ struct xmitQel *q = NULL; int oops; int i; int base = dev->base_addr; spin_lock_irqsave(&txqueue_lock, flags); if(QInIdle) { spin_unlock_irqrestore(&txqueue_lock, flags); return; } QInIdle = 1; spin_unlock_irqrestore(&txqueue_lock, flags); /* this tri-states the IRQ line */ (void) inb_p(base+6); oops = 100; loop: if (0>oops--) { printk("idle: looped too many times\n"); goto done; } state = inb_p(base+6); if (state != inb_p(base+6)) goto loop; switch(state) { case 0xfc: /* incoming command */ if (debug & DEBUG_LOWER) printk("idle: fc\n"); handlefc(dev); break; case 0xfd: /* incoming data */ if(debug & DEBUG_LOWER) printk("idle: fd\n"); handlefd(dev); break; case 0xf9: /* result ready */ if (debug & DEBUG_LOWER) printk("idle: f9\n"); if(!mboxinuse[0]) { mboxinuse[0] = 1; qels[0].cbuf = rescbuf; qels[0].cbuflen = 2; qels[0].dbuf = resdbuf; qels[0].dbuflen = 2; qels[0].QWrite = 0; qels[0].mailbox = 0; enQ(&qels[0]); } inb_p(dev->base_addr+1); inb_p(dev->base_addr+0); if( wait_timeout(dev,0xf9) ) printk("timed out idle f9\n"); break; case 0xf8: /* ?? */ if (xmQhd) { inb_p(dev->base_addr+1); inb_p(dev->base_addr+0); if(wait_timeout(dev,0xf8) ) printk("timed out idle f8\n"); } else { goto done; } break; case 0xfa: /* waiting for command */ if(debug & DEBUG_LOWER) printk("idle: fa\n"); if (xmQhd) { q=deQ(); memcpy(ltdmacbuf,q->cbuf,q->cbuflen); ltdmacbuf[1] = q->mailbox; if (debug>1) { int n; printk("ltpc: sent command "); n = q->cbuflen; if (n>100) n=100; for(i=0;i<n;i++) printk("%02x ",ltdmacbuf[i]); printk("\n"); } handlecommand(dev); if(0xfa==inb_p(base+6)) { /* we timed out, so return */ goto done; } } else { /* we don't seem to have a command */ if (!mboxinuse[0]) { mboxinuse[0] = 1; qels[0].cbuf = rescbuf; qels[0].cbuflen = 2; qels[0].dbuf = resdbuf; qels[0].dbuflen = 2; qels[0].QWrite = 0; qels[0].mailbox = 0; enQ(&qels[0]); } else { printk("trouble: response command already queued\n"); goto done; } } break; case 0Xfb: /* data transfer ready */ if(debug & DEBUG_LOWER) printk("idle: fb\n"); if(q->QWrite) { memcpy(ltdmabuf,q->dbuf,q->dbuflen); handlewrite(dev); } else { handleread(dev); /* non-zero mailbox numbers are for commmands, 0 is for GETRESULT requests */ if(q->mailbox) { memcpy(q->dbuf,ltdmabuf,q->dbuflen); } else { /* this was a result */ mailbox[ 0x0f & ltdmabuf[0] ] = ltdmabuf[1]; mboxinuse[0]=0; } } break; } goto loop; done: QInIdle=0; /* now set the interrupts back as appropriate */ /* the first read takes it out of tri-state (but still high) */ /* the second resets it */ /* note that after this point, any read of base+6 will trigger an interrupt */ if (dev->irq) { inb_p(base+7); inb_p(base+7); } return; }
int main(int argc, char *argv[]) { struct pollfd pfd[1]; char *ep, *cp; int on = 1; int send_time = 180; /* Default time, 180 seconds (3 minutes) */ struct sockaddr_in m_sin; uid_t unpriv_uid; gid_t unpriv_gid; long tmp; time_t delta = 0; struct timeval next, now; if (getuid()) errx(1, "not super user"); run_as(&unpriv_uid, &unpriv_gid); argv++; argc--; while (argc > 0 && *argv[0] == '-') { if (strcmp(*argv, "-m") == 0) { if (argc > 1 && *(argv + 1)[0] != '-') { /* Argument has been given */ argv++, argc--; multicast_mode = SCOPED_MULTICAST; tmp = strtol(*argv, &ep, 10); if (*ep != '\0' || tmp < INT_MIN || tmp > INT_MAX) errx(1, "invalid ttl: %s", *argv); multicast_scope = (int)tmp; if (multicast_scope > MAX_MULTICAST_SCOPE) errx(1, "ttl must not exceed %u", MAX_MULTICAST_SCOPE); } else multicast_mode = PER_INTERFACE_MULTICAST; } else if (strcmp(*argv, "-g") == 0) { if (argc > 1 && *(argv + 1)[0] != '-') { argv++, argc--; send_time = (int)strtol(*argv, &ep, 10); if (send_time <= 0) errx(1, "time must be greater than 0"); if (ep[0] != '\0') { if (ep[1] != '\0') errx(1, "invalid argument: %s", *argv); if (*ep == 'M' || *ep == 'm') { /* Time in minutes. */ send_time *= 60; } else errx(1, "invalid argument: %s", *argv); } if (send_time > 180) errx(1, "cannot be greater than 180 seconds (3 minutes)"); } else errx(1, "missing argument"); } else if (strcmp(*argv, "-i") == 0) insecure_mode = 1; else if (strcmp(*argv, "-l") == 0) quiet_mode = 1; else if (strcmp(*argv, "-p") == 0) iff_flag = 0; else usage(); argv++, argc--; } if (argc > 0) usage(); #ifndef DEBUG struct pidfh *pfh = NULL; pfh = pidfile_open(NULL, 600, NULL); daemon(1, 0); pidfile_write(pfh); #endif signal(SIGHUP, hup); openlog("rwhod", LOG_PID, LOG_DAEMON); sp = getservbyname("who", "udp"); if (sp == NULL) quit("udp/who: unknown service", WITHOUT_ERRNO); if (chdir(_PATH_RWHODIR) < 0) quit(_PATH_RWHODIR, WITH_ERRNO); /* * Establish host name as returned by system. */ if (gethostname(myname, sizeof(myname)) < 0) quit("gethostname", WITH_ERRNO); if ((cp = strchr(myname, '.')) != NULL) *cp = '\0'; strlcpy(mywd.wd_hostname, myname, sizeof(mywd.wd_hostname)); utmpf = open(_PATH_UTMP, O_RDONLY|O_CREAT, 0644); if (utmpf < 0) quit(_PATH_UTMP, WITH_ERRNO); getboottime(); if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) quit("socket", WITH_ERRNO); if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) quit("setsockopt SO_BROADCAST", WITH_ERRNO); memset(&m_sin, 0, sizeof(m_sin)); m_sin.sin_len = sizeof(m_sin); m_sin.sin_family = AF_INET; m_sin.sin_port = sp->s_port; if (bind(s, (struct sockaddr *)&m_sin, sizeof(m_sin)) < 0) quit("bind", WITH_ERRNO); setgid(unpriv_gid); setgroups(1, &unpriv_gid); /* XXX BOGUS groups[0] = egid */ setuid(unpriv_uid); if (!configure(s)) exit(1); if (!quiet_mode) { send_host_information(); delta = send_time; gettimeofday(&now, NULL); timeadd(&now, delta, &next); } pfd[0].fd = s; pfd[0].events = POLLIN; for (;;) { int n; n = poll(pfd, 1, 1000); if (onsighup) { onsighup = 0; getboottime(); } if (n == 1) handleread(s); if (!quiet_mode) { gettimeofday(&now, NULL); if (now.tv_sec > next.tv_sec) { send_host_information(); timeadd(&now, delta, &next); } } } }
int main(int argc, char *argv[]) { struct sockaddr_in sockname; int max = -1, omax; /* the biggest value sd. for select */ int sd; /* our listen socket */ fd_set *readable = NULL , *writable = NULL; /* fd_sets for select */ u_short port; u_long p; char *ep; int i; /* * first, figure out what port we will listen on - it should * be our first parameter. */ if (argc != 2) usage(); errno = 0; p = strtoul(argv[1], &ep, 10); if (*argv[1] == '\0' || *ep != '\0') { /* parameter wasn't a number, or was empty */ fprintf(stderr, "%s - not a number\n", argv[1]); usage(); } if ((errno == ERANGE && p == ULONG_MAX) || (p > USHRT_MAX)) { /* It's a number, but it either can't fit in an unsigned * long, or is too big for an unsigned short */ fprintf(stderr, "%s - value out of range\n", argv[1]); usage(); } /* now safe to do this */ port = p; /* now before we get going, decide if we want to daemonize, that * is, run in the background like a real system process */ #ifndef DEBUG /* don't daemonize if we compile with -DDEBUG */ if (daemon(1, 0) == -1) err(1, "daemon() failed"); #endif /* now off to the races - let's set up our listening socket */ memset(&sockname, 0, sizeof(sockname)); sockname.sin_family = AF_INET; sockname.sin_port = htons(port); sockname.sin_addr.s_addr = htonl(INADDR_ANY); sd=socket(AF_INET,SOCK_STREAM,0); if ( sd == -1) err(1, "socket failed"); if (bind(sd, (struct sockaddr *) &sockname, sizeof(sockname)) == -1) err(1, "bind failed"); if (listen(sd,3) == -1) err(1, "listen failed"); /* * We're now bound, and listening for connections on "sd". * Each call to "accept" will return us a descriptor talking to * a connected client. */ /* * finally - the main loop. accept connections and deal with 'em */ #ifndef DEBUG /* * since we'll be running as a daemon if we're not compiled with * -DDEBUG, we better not be using printf - since stdout will be * unusable */ printf("Server up and listening for connections on port %u\n", port); #endif /* initialize all our connection structures */ for (i = 0; i < MAXCONN; i++) closecon(&connections[i], 1); for(;;) { int i; int maxfd = -1; /* the biggest value sd we are interested in.*/ /* * first we have to initialize the fd_sets to keep * track of readable and writable sockets. we have * to make sure we have fd_sets that are big enough * to hold our largest valued socket descriptor. * so first, we find the max value by iterating through * all the connections, and then we allocate fd sets * that are big enough, if they aren't already. */ omax = max; max = sd; /* the listen socket */ for (i = 0; i < MAXCONN; i++) { if (connections[i].sd > max) max = connections[i].sd; } if (max > omax) { /* we need bigger fd_sets allocated */ /* free the old ones - does nothing if they are NULL */ free(readable); free(writable); /* * this is how to allocate fd_sets for select */ readable = (fd_set *)calloc(howmany(max + 1, NFDBITS), sizeof(fd_mask)); if (readable == NULL) err(1, "out of memory"); writable = (fd_set *)calloc(howmany(max + 1, NFDBITS), sizeof(fd_mask)); if (writable == NULL) err(1, "out of memory"); omax = max; /* * note that calloc always returns 0'ed memory, * (unlike malloc) so these sets are all set to 0 * and ready to go */ } else { /* * our allocated sets are big enough, just make * sure they are cleared to 0. */ memset(readable, 0, howmany(max+1, NFDBITS) * sizeof(fd_mask)); memset(writable, 0, howmany(max+1, NFDBITS) * sizeof(fd_mask)); } /* * Now, we decide which sockets we are interested * in reading and writing, by setting the corresponding * bit in the readable and writable fd_sets. */ /* * we are always interesting in reading from the * listening socket. so put it in the read set. */ FD_SET(sd, readable); if (maxfd < sd) maxfd = sd; /* * now go through the list of connections, and if we * are interested in reading from, or writing to, the * connection's socket, put it in the readable, or * writable fd_set - in preparation to call select * to tell us which ones we can read and write to. */ for (i = 0; i<MAXCONN; i++) { if (connections[i].state == STATE_READING) { FD_SET(connections[i].sd, readable); if (maxfd < connections[i].sd) maxfd = connections[i].sd; } if (connections[i].state == STATE_WRITING) { FD_SET(connections[i].sd, writable); if (maxfd < connections[i].sd) maxfd = connections[i].sd; } } /* * finally, we can call select. we have filled in "readable" * and "writable" with everything we are interested in, and * when select returns, it will indicate in each fd_set * which sockets are readable and writable */ i = select(maxfd + 1, readable, writable, NULL,NULL); if (i == -1 && errno != EINTR) err(1, "select failed"); if (i > 0) { /* something is readable or writable... */ /* * First things first. check the listen socket. * If it was readable - we have a new connection * to accept. */ if (FD_ISSET(sd, readable)) { struct con *cp; int newsd; socklen_t slen; struct sockaddr_in sa; slen = sizeof(sa); newsd = accept(sd, (struct sockaddr *)&sa, &slen); if (newsd == -1) err(1, "accept failed"); cp = get_free_conn(); if (cp == NULL) { /* * we have no connection structures * so we close connection to our * client to not leave him hanging * because we are too busy to * service his request */ close(newsd); } else { /* * ok, if this worked, we now have a * new connection. set him up to be * READING so we do something with him */ cp->state = STATE_READING; cp->sd = newsd; cp->slen = slen; memcpy(&cp->sa, &sa, sizeof(sa)); } } /* * now, iterate through all of our connections, * check to see if they are readble or writable, * and if so, do a read or write accordingly */ for (i = 0; i<MAXCONN; i++) { if ((connections[i].state == STATE_READING) && FD_ISSET(connections[i].sd, readable)) handleread(&connections[i]); if ((connections[i].state == STATE_WRITING) && FD_ISSET(connections[i].sd, writable)) handlewrite(&connections[i]); } } } }
static uae_u32 REGPARAM2 uaenet_int_handler (TrapContext *ctx) { int i, j; int gotit; struct asyncreq *ar; if (uae_sem_trywait (&async_sem)) { uaenet_int_requested = 0; uaenet_int_late = 1; return 0; } for (i = 0; i < MAX_OPEN_DEVICES; i++) pdevst[i].tmp = 0; for (i = 0; i < MAX_TOTAL_NET_DEVICES; i++) { struct s2devstruct *dev = &devst[i]; struct s2packet *p; if (dev->online) { while (dev->readqueue) { uae_u16 type; p = dev->readqueue; type = (p->data[2 * ADDR_SIZE] << 8) | p->data[2 * ADDR_SIZE + 1]; ar = dev->ar; gotit = 0; while (ar) { if (!ar->ready) { uaecptr request = ar->request; int command = get_word (request + 28); uae_u32 packettype = get_long (request + 32 + 4); if (command == CMD_READ && (packettype == type || (packettype <= 1500 && type <= 1500))) { struct priv_s2devstruct *pdev = getps2devstruct (request); if (pdev && pdev->tmp == 0) { if (handleread (ctx, pdev, request, p->data, p->len, command)) { if (log_net) write_log (_T("-> %p Accepted, CMD_READ, REQ=%08X LEN=%d\n"), p, request, p->len); ar->ready = 1; write_comm_pipe_u32 (&dev->requests, request, 1); dev->packetsreceived++; gotit = 1; pdev->tmp = 1; } else { if (log_net) write_log (_T("-> %p PacketFilter() rejected, CMD_READ, REQ=%08X LEN=%d\n"), p, request, p->len); pdev->tmp = -1; } } } } ar = ar->next; } ar = dev->ar; while (ar) { if (!ar->ready) { uaecptr request = ar->request; int command = get_word (request + 28); if (command == S2_READORPHAN) { struct priv_s2devstruct *pdev = getps2devstruct (request); if (pdev && pdev->tmp <= 0) { if (log_net) write_log (_T("-> %p Accepted, S2_READORPHAN, REQ=%08X LEN=%d\n"), p, request, p->len); handleread (ctx, pdev, request, p->data, p->len, command); ar->ready = 1; write_comm_pipe_u32 (&dev->requests, request, 1); dev->packetsreceived++; dev->unknowntypesreceived++; gotit = 1; pdev->tmp = 1; } } } ar = ar->next; } if (!gotit) { if (log_net) write_log (_T("-> %p packet dropped, LEN=%d\n"), p, p->len); for (j = 0; j < MAX_OPEN_DEVICES; j++) { if (pdevst[j].unit == dev->unit) { if (pdevst[j].tracks[type]) pdevst[j].packetsdropped++; } } } dev->readqueue = dev->readqueue->next; freepacket (p); } } else { while (dev->readqueue) { p = dev->readqueue; dev->readqueue = dev->readqueue->next; freepacket (p); } } ar = dev->ar; while (ar) { if (!ar->ready) { uaecptr request = ar->request; int command = get_word (request + 28); if (command == S2_ONLINE) { struct priv_s2devstruct *pdev = getps2devstruct (request); dev->packetsreceived = 0; dev->packetssent = 0; dev->baddata = 0; dev->overruns = 0; dev->unknowntypesreceived = 0; dev->reconfigurations = 0; if (pdev && pdev->timerbase) { m68k_areg (regs, 0) = pdev->tempbuf; CallLib (ctx, pdev->timerbase, -0x42); /* GetSysTime() */ } else { put_long (pdev->tempbuf + 0, 0); put_long (pdev->tempbuf + 4, 0); } dev->online_secs = get_long (pdev->tempbuf + 0); dev->online_micro = get_long (pdev->tempbuf + 4); checkevents (dev, S2EVENT_ONLINE, 0); dev->online = 1; ar->ready = 1; write_comm_pipe_u32 (&dev->requests, request, 1); uaenet_vsync_requested--; } else if (command == CMD_FLUSH) { /* do not reply CMD_FLUSH until all other requests are gone */ if (dev->ar->next == NULL) { if (log_net) write_log (_T("CMD_FLUSH replied %08x\n"), request); ar->ready = 1; write_comm_pipe_u32 (&dev->requests, request, 1); uaenet_vsync_requested--; } else { struct priv_s2devstruct *pdev = getps2devstruct (request); if (pdev) { dev->flush_timeout--; if (dev->flush_timeout <= 0) { dev->flush_timeout = FLUSH_TIMEOUT; if (dev->flush_timeout_cnt > 1) write_log (_T("WARNING: %s:%d CMD_FLUSH possibly frozen..\n"), getdevname(), pdev->unit); dev->flush_timeout_cnt++; flush (pdev); } } } } } ar = ar->next; } } if (uaenet_int_late) uaenet_int_requested = 1; else uaenet_int_requested = 0; uaenet_int_late = 0; uae_sem_post (&async_sem); return 0; }