/*------------------------------------------------------------------------ * ipfcons - construct a single packet from an IP fragment queue *------------------------------------------------------------------------ */ struct ep * ipfcons(struct ipfq *iq) { struct ep *pep, *peptmp; struct ip *pip; int off, seq; pep = (struct ep *)getbuf(Net.lrgpool); if (pep == (struct ep *)SYSERR) { while (peptmp = (struct ep *)deq(iq->ipf_q)) { IpReasmFails++; freebuf(peptmp); } freeq(iq->ipf_q); iq->ipf_state = IPFF_FREE; return 0; } /* copy the Ether and IP headers */ peptmp = (struct ep *)deq(iq->ipf_q); pip = (struct ip *)peptmp->ep_data; off = IP_HLEN(pip); seq = 0; memcpy(pep, peptmp, EP_HLEN+off); /* copy the data */ while (peptmp != 0) { int dlen, doff; pip = (struct ip *)peptmp->ep_data; doff = IP_HLEN(pip) + seq - ((pip->ip_fragoff&IP_FRAGOFF)<<3); dlen = pip->ip_len - doff; memcpy(pep->ep_data+off, peptmp->ep_data+doff, dlen); off += dlen; seq += dlen; freebuf(peptmp); peptmp = (struct ep *)deq(iq->ipf_q); } /* fix the large packet header */ pip = (struct ip *)pep->ep_data; pip->ip_len = off; pip->ip_fragoff = 0; /* release resources */ freeq(iq->ipf_q); iq->ipf_state = IPFF_FREE; IpReasmOKs++; return pep; }
/*------------------------------------------------------------------------ * arpqsend - write packets queued waiting for an ARP resolution *------------------------------------------------------------------------ */ void arpqsend(struct arpentry *pae) { struct ep *pep; struct netif *pni; if (pae->ae_queue == EMPTY) return; pni = pae->ae_pni; while (pep = (struct ep *)deq(pae->ae_queue)) netwrite(pni, pep, pep->ep_len); freeq(pae->ae_queue); pae->ae_queue = EMPTY; }
/* * Display the current state of the queue. Format = 1 if long format. */ void displayq(int format) { struct queue *q; int i, nitems, fd, ret; char *cp, *ecp; struct queue **queue; struct stat statb; FILE *fp; lflag = format; totsize = 0; rank = -1; getprintcap(printer); /* * Print out local queue * Find all the control files in the spooling directory */ seteuid(euid); if (chdir(SD) < 0) fatal("cannot chdir to spooling directory"); seteuid(uid); if ((nitems = getq(&queue)) < 0) fatal("cannot examine spooling area\n"); seteuid(euid); ret = stat(LO, &statb); seteuid(uid); if (ret >= 0) { if (statb.st_mode & S_IXUSR) { if (remote) printf("%s: ", host); printf("Warning: %s is down: ", printer); seteuid(euid); fd = open(ST, O_RDONLY); seteuid(uid); if (fd >= 0) { (void)flock(fd, LOCK_SH); while ((i = read(fd, line, sizeof(line))) > 0) (void)fwrite(line, 1, (size_t)i, stdout); (void)close(fd); /* unlocks as well */ } else putchar('\n'); } if (statb.st_mode & S_IXGRP) { if (remote) printf("%s: ", host); printf("Warning: %s queue is turned off\n", printer); } } if (nitems) { seteuid(euid); fp = fopen(LO, "r"); seteuid(uid); if (fp == NULL) nodaemon(); else { /* get daemon pid */ cp = current; ecp = cp + sizeof(current) - 1; while ((i = getc(fp)) != EOF && i != '\n') { if (cp < ecp) *cp++ = i; } *cp = '\0'; i = atoi(current); if (i <= 0) { ret = -1; } else { seteuid(euid); ret = kill(i, 0); seteuid(uid); } if (ret < 0) { nodaemon(); } else { /* read current file name */ cp = current; ecp = cp + sizeof(current) - 1; while ((i = getc(fp)) != EOF && i != '\n') { if (cp < ecp) *cp++ = i; } *cp = '\0'; /* * Print the status file. */ if (remote) printf("%s: ", host); seteuid(euid); fd = open(ST, O_RDONLY); seteuid(uid); if (fd >= 0) { (void)flock(fd, LOCK_SH); while ((i = read(fd, line, sizeof(line))) > 0) (void)fwrite(line, 1, (size_t)i, stdout); (void)close(fd); /* unlocks as well */ } else putchar('\n'); } (void)fclose(fp); } /* * Now, examine the control files and print out the jobs to * be done for each user. */ if (!lflag) header(); for (i = 0; i < nitems; i++) { q = queue[i]; inform(q->q_name); } } freeq(queue, nitems); if (!remote) { if (nitems == 0) puts("no entries"); return; } /* * Print foreign queue * Note that a file in transit may show up in either queue. */ if (nitems) putchar('\n'); (void)snprintf(line, sizeof(line), "%c%s", format + '\3', RP); cp = line; ecp = line + sizeof(line); for (i = 0; i < requests && (size_t)(cp - line + 11) < sizeof(line) - 2; i++) { cp += strlen(cp); (void)snprintf(cp, ecp - cp, " %d", requ[i]); } for (i = 0; i < users && cp - line + 1 + strlen(user[i]) < sizeof(line) - 2; i++) { cp += strlen(cp); if ((size_t)(cp - line) > sizeof(line) - 2) break; *cp++ = ' '; /* truncation may happen */ (void)strlcpy(cp, user[i], ecp - cp); } (void)strlcat(line, "\n", sizeof(line)); fd = getport(RM); if (fd < 0) { if (from != host) printf("%s: ", host); (void)printf("connection to %s is down\n", RM); } else { struct sigaction osa, nsa; i = strlen(line); if (write(fd, line, (size_t)i) != i) fatal("Lost connection"); nsa.sa_handler = alarmer; sigemptyset(&nsa.sa_mask); sigaddset(&nsa.sa_mask, SIGALRM); nsa.sa_flags = 0; (void)sigaction(SIGALRM, &nsa, &osa); alarm(wait_time); while ((i = read(fd, line, sizeof(line))) > 0) { (void)fwrite(line, 1, (size_t)i, stdout); alarm(wait_time); } alarm(0); (void)sigaction(SIGALRM, &osa, NULL); (void)close(fd); } }