void init_opcodes(void) { unsigned int i; #ifdef PIKE_DEBUG int fatal_later=0; #ifdef INSTR_PROFILING instr_counter_storage=init_instr_storage_pointers(p_flag); #endif #endif for(i=0; i<NELEM(instr_names);i++) { #ifdef PIKE_DEBUG if(instr_names[i].token >= F_MAX_INSTR) { fprintf(stderr,"Error in instr_names[%u]\n\n",i); fatal_later++; } if(instrs[instr_names[i].token - F_OFFSET].name) { fprintf(stderr,"Duplicate name for %s\n",instr_names[i].word); fatal_later++; } #endif instrs[instr_names[i].token - F_OFFSET].name = instr_names[i].word; instrs[instr_names[i].token - F_OFFSET].flags=instr_names[i].flags; #ifdef PIKE_USE_MACHINE_CODE instrs[instr_names[i].token - F_OFFSET].address=instr_names[i].address; #endif } #ifdef PIKE_USE_MACHINE_CODE instrs_checksum = hashmem((const unsigned char*)instrs, sizeof(instrs), sizeof(struct instr)); /* fprintf(stderr, "Instruction checksum: %d\n", instrs_checksum); */ #endif /* PIKE_USE_MACHINE_CODE */ #ifdef PIKE_DEBUG for(i=1; i<F_MAX_OPCODE-F_OFFSET;i++) { if(!instrs[i].name) { fprintf(stderr,"Opcode %d does not have a name.\n",i); fatal_later++; } } if(fatal_later) Pike_fatal("Found %d errors in instrs.\n",fatal_later); #endif }
/* * NAME: conn->del() * DESCRIPTION: delete a connection */ void conn_del(connection *conn) { connection **hash; if (conn->fd >= 0) { close(conn->fd); FD_CLR(conn->fd, &infds); FD_CLR(conn->fd, &outfds); FD_CLR(conn->fd, &waitfds); conn->fd = -1; } else { --closed; } if (conn->udpbuf != (char *) NULL) { if (conn->chain.name != (char *) NULL) { hash = (connection **) ht_lookup(chtab, conn->chain.name, FALSE); # ifdef INET6 } else if (conn->addr->ipnum.ipv6) { hash = &udphtab[(hashmem((char *) &conn->addr->ipnum, sizeof(struct in6_addr)) ^ conn->uport) % udphtabsz]; # endif } else { hash = &udphtab[(((Uint) conn->addr->ipnum.in.addr.s_addr) ^ conn->uport) % udphtabsz]; } while (*hash != conn) { hash = (connection **) &(*hash)->chain.next; } *hash = (connection *) conn->chain.next; npackets -= conn->npkts; FREE(conn->udpbuf); } #ifndef NETWORK_EXTENSIONS ipa_del(conn->addr); #else if (conn->addr != (ipaddr *) NULL) { ipa_del(conn->addr); } #endif conn->chain.next = (hte *) flist; flist = conn; }
/* * NAME: ipaddr->new() * DESCRIPTION: return a new ipaddr */ static ipaddr *ipa_new(in46addr *ipnum) { ipaddr *ipa, **hash; /* check hash table */ # ifdef INET6 if (ipnum->ipv6) { hash = &ipahtab[hashmem((char *) ipnum, sizeof(struct in6_addr)) % ipahtabsz]; } else # endif { hash = &ipahtab[(Uint) ipnum->in.addr.s_addr % ipahtabsz]; } while (*hash != (ipaddr *) NULL) { ipa = *hash; # ifdef INET6 if (ipnum->ipv6 == ipa->ipnum.ipv6 && ((ipnum->ipv6) ? memcmp(&ipnum->in.addr6, &ipa->ipnum.in.addr6, sizeof(struct in6_addr)) == 0 : ipnum->in.addr.s_addr == ipa->ipnum.in.addr.s_addr)) { # else if (ipnum->in.addr.s_addr == ipa->ipnum.in.addr.s_addr) { # endif /* * found it */ if (ipa->ref == 0) { /* remove from free list */ if (ipa->prev == (ipaddr *) NULL) { ffirst = ipa->next; } else { ipa->prev->next = ipa->next; } if (ipa->next == (ipaddr *) NULL) { flast = ipa->prev; } else { ipa->next->prev = ipa->prev; } ipa->prev = ipa->next = (ipaddr *) NULL; --nfree; } ipa->ref++; if (ipa->name[0] == '\0' && ipa != lastreq && ipa->prev == (ipaddr *) NULL && ipa != qhead) { if (!busy) { /* send query to name resolver */ write(out, (char *) ipnum, sizeof(in46addr)); lastreq = ipa; busy = TRUE; } else { /* put in request queue */ ipa->prev = qtail; if (qtail == (ipaddr *) NULL) { qhead = ipa; } else { qtail->next = ipa; } qtail = ipa; } } return ipa; } hash = &ipa->link; } if (nfree >= NFREE) { ipaddr **h; /* * use first ipaddr in free list */ ipa = ffirst; ffirst = ipa->next; ffirst->prev = (ipaddr *) NULL; --nfree; if (ipa == lastreq) { lastreq = (ipaddr *) NULL; } if (hash != &ipa->link) { /* remove from hash table */ # ifdef INET6 if (ipa->ipnum.ipv6) { h = &ipahtab[hashmem((char *) &ipa->ipnum, sizeof(struct in6_addr)) % ipahtabsz]; } else # endif { h = &ipahtab[(Uint) ipa->ipnum.in.addr.s_addr % ipahtabsz]; } while (*h != ipa) { h = &(*h)->link; } *h = ipa->link; /* put in hash table */ ipa->link = *hash; *hash = ipa; } } else { /* * allocate new ipaddr */ m_static(); ipa = ALLOC(ipaddr, 1); m_dynamic(); /* put in hash table */ ipa->link = *hash; *hash = ipa; } ipa->ref = 1; ipa->ipnum = *ipnum; ipa->name[0] = '\0'; ipa->prev = ipa->next = (ipaddr *) NULL; if (!busy) { /* send query to name resolver */ write(out, (char *) ipnum, sizeof(in46addr)); lastreq = ipa; busy = TRUE; } else { /* put in request queue */ ipa->prev = qtail; if (qtail == (ipaddr *) NULL) { qhead = ipa; } else { qtail->next = ipa; } qtail = ipa; } return ipa; } /* * NAME: ipaddr->del() * DESCRIPTION: delete an ipaddr */ static void ipa_del(ipaddr *ipa) { if (--ipa->ref == 0) { if (ipa->prev != (ipaddr *) NULL || qhead == ipa) { /* remove from queue */ if (ipa->prev != (ipaddr *) NULL) { ipa->prev->next = ipa->next; } else { qhead = ipa->next; } if (ipa->next != (ipaddr *) NULL) { ipa->next->prev = ipa->prev; } else { qtail = ipa->prev; } } /* add to free list */ if (flast != (ipaddr *) NULL) { flast->next = ipa; ipa->prev = flast; flast = ipa; } else { ffirst = flast = ipa; ipa->prev = (ipaddr *) NULL; } ipa->next = (ipaddr *) NULL; nfree++; } } /* * NAME: ipaddr->lookup() * DESCRIPTION: lookup another ip name */ static void ipa_lookup() { ipaddr *ipa; if (lastreq != (ipaddr *) NULL) { /* read ip name */ lastreq->name[read(in, lastreq->name, MAXHOSTNAMELEN)] = '\0'; } else { char buf[MAXHOSTNAMELEN]; /* discard ip name */ read(in, buf, MAXHOSTNAMELEN); } /* if request queue not empty, write new query */ if (qhead != (ipaddr *) NULL) { ipa = qhead; write(out, (char *) &ipa->ipnum, sizeof(in46addr)); qhead = ipa->next; if (qhead == (ipaddr *) NULL) { qtail = (ipaddr *) NULL; } else { qhead->prev = (ipaddr *) NULL; } ipa->prev = ipa->next = (ipaddr *) NULL; lastreq = ipa; busy = TRUE; } else { lastreq = (ipaddr *) NULL; busy = FALSE; } }
/* * NAME: conn->udprecv6() * DESCRIPTION: receive an UDP packet */ static void conn_udprecv6(int n) { char buffer[BINBUF_SIZE]; struct sockaddr_in6 from; unsigned int fromlen; int size; connection **hash, *conn; char *p; memset(buffer, '\0', UDPHASHSZ); fromlen = sizeof(struct sockaddr_in6); size = recvfrom(udescs[n].in6, buffer, BINBUF_SIZE, 0, (struct sockaddr *) &from, &fromlen); if (size < 0) { return; } hash = &udphtab[(hashmem((char *) &from.sin6_addr, sizeof(struct in6_addr)) ^ from.sin6_port) % udphtabsz]; for (;;) { conn = *hash; if (conn == (connection *) NULL) { /* * see if the packet matches an outstanding challenge */ hash = (connection **) ht_lookup(chtab, buffer, FALSE); while ((conn=*hash) != (connection *) NULL && memcmp(conn->chain.name, buffer, UDPHASHSZ) == 0) { if (conn->bufsz == size && memcmp(conn->udpbuf, buffer, size) == 0 && conn->addr->ipnum.ipv6 && memcmp(&conn->addr->ipnum, &from.sin6_addr, sizeof(struct in6_addr)) == 0) { /* * attach new UDP channel */ *hash = (connection *) conn->chain.next; conn->chain.name = (char *) NULL; conn->bufsz = 0; conn->uport = from.sin6_port; hash = &udphtab[(hashmem((char *) &from.sin6_addr, sizeof(struct in6_addr)) ^ conn->uport) % udphtabsz]; conn->chain.next = (hte *) *hash; *hash = conn; break; } hash = (connection **) &conn->chain.next; } break; } if (conn->at == n && conn->uport == from.sin6_port && memcmp(&conn->addr->ipnum, &from.sin6_addr, sizeof(struct in6_addr)) == 0) { /* * packet from known correspondent */ if (conn->bufsz + size <= BINBUF_SIZE - 2) { p = conn->udpbuf + conn->bufsz; *p++ = size >> 8; *p++ = size; memcpy(p, buffer, size); conn->bufsz += size + 2; conn->npkts++; npackets++; } break; } hash = (connection **) &conn->chain.next; }