void ipx_printhost(struct ipx_addr *addr) { u_short port; struct ipx_addr work = *addr; char *p; u_char *q; char *net = "", *host = ""; char cport[10], chost[15], cnet[15]; port = ntohs(work.x_port); if (ipx_nullnet(work) && ipx_nullhost(work)) { if (port) kprintf("*.%x", port); else kprintf("*.*"); return; } if (ipx_wildnet(work)) net = "any"; else if (ipx_nullnet(work)) net = "*"; else { q = work.x_net.c_net; ksnprintf(cnet, sizeof(cnet), "%x%x%x%x", q[0], q[1], q[2], q[3]); for (p = cnet; *p == '0' && p < cnet + 8; p++) continue; net = p; } if (ipx_wildhost(work)) host = "any"; else if (ipx_nullhost(work)) host = "*"; else { q = work.x_host.c_host; ksnprintf(chost, sizeof(chost), "%x%x%x%x%x%x", q[0], q[1], q[2], q[3], q[4], q[5]); for (p = chost; *p == '0' && p < chost + 12; p++) continue; host = p; } if (port) { if (strcmp(host, "*") == 0) { host = ""; ksnprintf(cport, sizeof(cport), "%x", port); } else ksnprintf(cport, sizeof(cport), ".%x", port); } else *cport = 0; kprintf("%s.%s%s", net, host, cport); }
void ipxprotopr(u_long off, const char *name, int af1 __unused, int proto __unused) { struct ipxpcbhead cb; struct ipxpcb *ipxp; struct ipxpcb ipxpcb; struct spxpcb spxpcb; struct socket sockb; static int first = 1; int isspx; if (off == 0) return; isspx = strcmp(name, "spx") == 0; kread(off, (char *)&cb, sizeof (struct ipxpcbhead)); ipxp = LIST_FIRST(&cb); while (ipxp != NULL) { u_long ppcb; kread((u_long)ipxp, (char *)&ipxpcb, sizeof (ipxpcb)); ipxp = LIST_NEXT(&ipxpcb, ipxp_list); if (!aflag && ipx_nullhost(ipxpcb.ipxp_faddr) ) { continue; } kread((u_long)ipxpcb.ipxp_socket, (char *)&sockb, sizeof (sockb)); ppcb = (u_long) ipxpcb.ipxp_pcb; if (ppcb) { if (isspx) { kread(ppcb, (char *)&spxpcb, sizeof (spxpcb)); } else continue; } else if (isspx) continue; if (first) { printf("Active IPX connections"); if (aflag) printf(" (including servers)"); putchar('\n'); if (Aflag) printf("%-8.8s ", "PCB"); printf(Aflag ? "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" : "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n", "Proto", "Recv-Q", "Send-Q", "Local Address", "Foreign Address", "(state)"); first = 0; } if (Aflag) printf("%8lx ", ppcb); printf("%-5.5s %6u %6u ", name, sockb.so_rcv.sb_cc, sockb.so_snd.sb_cc); printf(Aflag?" %-18.18s":" %-22.22s", ipx_prpr(&ipxpcb.ipxp_laddr)); printf(Aflag?" %-18.18s":" %-22.22s", ipx_prpr(&ipxpcb.ipxp_faddr)); if (isspx) { if (spxpcb.s_state >= TCP_NSTATES) printf(" %d", spxpcb.s_state); else printf(" %s", tcpstates[spxpcb.s_state]); } putchar('\n'); } }
void spx_input(struct mbuf *m, struct ipxpcb *ipxp) { struct spxpcb *cb; struct spx *si = mtod(m, struct spx *); struct socket *so; struct spx spx_savesi; int dropsocket = 0; short ostate = 0; spxstat.spxs_rcvtotal++; KASSERT(ipxp != NULL, ("spx_input: ipxpcb == NULL")); /* * spx_input() assumes that the caller will hold both the pcb list * lock and also the ipxp lock. spx_input() will release both before * returning, and may in fact trade in the ipxp lock for another pcb * lock following sonewconn(). */ IPX_LIST_LOCK_ASSERT(); IPX_LOCK_ASSERT(ipxp); cb = ipxtospxpcb(ipxp); KASSERT(cb != NULL, ("spx_input: cb == NULL")); if (ipxp->ipxp_flags & IPXP_DROPPED) goto drop; if (m->m_len < sizeof(*si)) { if ((m = m_pullup(m, sizeof(*si))) == NULL) { IPX_UNLOCK(ipxp); IPX_LIST_UNLOCK(); spxstat.spxs_rcvshort++; return; } si = mtod(m, struct spx *); } si->si_seq = ntohs(si->si_seq); si->si_ack = ntohs(si->si_ack); si->si_alo = ntohs(si->si_alo); so = ipxp->ipxp_socket; KASSERT(so != NULL, ("spx_input: so == NULL")); #ifdef MAC if (mac_socket_check_deliver(so, m) != 0) goto drop; #endif if (so->so_options & SO_DEBUG || traceallspxs) { ostate = cb->s_state; spx_savesi = *si; } if (so->so_options & SO_ACCEPTCONN) { struct spxpcb *ocb = cb; so = sonewconn(so, 0); if (so == NULL) goto drop; /* * This is ugly, but .... * * Mark socket as temporary until we're committed to keeping * it. The code at ``drop'' and ``dropwithreset'' check the * flag dropsocket to see if the temporary socket created * here should be discarded. We mark the socket as * discardable until we're committed to it below in * TCPS_LISTEN. * * XXXRW: In the new world order of real kernel parallelism, * temporarily allocating the socket when we're "not sure" * seems like a bad idea, as we might race to remove it if * the listen socket is closed...? * * We drop the lock of the listen socket ipxp, and acquire * the lock of the new socket ippx. */ dropsocket++; IPX_UNLOCK(ipxp); ipxp = (struct ipxpcb *)so->so_pcb; IPX_LOCK(ipxp); ipxp->ipxp_laddr = si->si_dna; cb = ipxtospxpcb(ipxp); cb->s_mtu = ocb->s_mtu; /* preserve sockopts */ cb->s_flags = ocb->s_flags; /* preserve sockopts */ cb->s_flags2 = ocb->s_flags2; /* preserve sockopts */ cb->s_state = TCPS_LISTEN; } IPX_LOCK_ASSERT(ipxp); /* * Packet received on connection. Reset idle time and keep-alive * timer. */ cb->s_idle = 0; cb->s_timer[SPXT_KEEP] = SPXTV_KEEP; switch (cb->s_state) { case TCPS_LISTEN:{ struct sockaddr_ipx *sipx, ssipx; struct ipx_addr laddr; /* * If somebody here was carying on a conversation and went * away, and his pen pal thinks he can still talk, we get the * misdirected packet. */ if (spx_hardnosed && (si->si_did != 0 || si->si_seq != 0)) { spx_istat.gonawy++; goto dropwithreset; } sipx = &ssipx; bzero(sipx, sizeof *sipx); sipx->sipx_len = sizeof(*sipx); sipx->sipx_family = AF_IPX; sipx->sipx_addr = si->si_sna; laddr = ipxp->ipxp_laddr; if (ipx_nullhost(laddr)) ipxp->ipxp_laddr = si->si_dna; if (ipx_pcbconnect(ipxp, (struct sockaddr *)sipx, &thread0)) { ipxp->ipxp_laddr = laddr; spx_istat.noconn++; goto drop; } spx_template(cb); dropsocket = 0; /* committed to socket */ cb->s_did = si->si_sid; cb->s_rack = si->si_ack; cb->s_ralo = si->si_alo; #define THREEWAYSHAKE #ifdef THREEWAYSHAKE cb->s_state = TCPS_SYN_RECEIVED; cb->s_force = 1 + SPXT_KEEP; spxstat.spxs_accepts++; cb->s_timer[SPXT_KEEP] = SPXTV_KEEP; } break; case TCPS_SYN_RECEIVED: { /* * This state means that we have heard a response to our * acceptance of their connection. It is probably logically * unnecessary in this implementation. */ if (si->si_did != cb->s_sid) { spx_istat.wrncon++; goto drop; } #endif ipxp->ipxp_fport = si->si_sport; cb->s_timer[SPXT_REXMT] = 0; cb->s_timer[SPXT_KEEP] = SPXTV_KEEP; soisconnected(so); cb->s_state = TCPS_ESTABLISHED; spxstat.spxs_accepts++; } break; case TCPS_SYN_SENT: /* * This state means that we have gotten a response to our * attempt to establish a connection. We fill in the data * from the other side, telling us which port to respond to, * instead of the well-known one we might have sent to in the * first place. We also require that this is a response to * our connection id. */ if (si->si_did != cb->s_sid) { spx_istat.notme++; goto drop; } spxstat.spxs_connects++; cb->s_did = si->si_sid; cb->s_rack = si->si_ack; cb->s_ralo = si->si_alo; cb->s_dport = ipxp->ipxp_fport = si->si_sport; cb->s_timer[SPXT_REXMT] = 0; cb->s_flags |= SF_ACKNOW; soisconnected(so); cb->s_state = TCPS_ESTABLISHED; /* * Use roundtrip time of connection request for initial rtt. */ if (cb->s_rtt) { cb->s_srtt = cb->s_rtt << 3; cb->s_rttvar = cb->s_rtt << 1; SPXT_RANGESET(cb->s_rxtcur, ((cb->s_srtt >> 2) + cb->s_rttvar) >> 1, SPXTV_MIN, SPXTV_REXMTMAX); cb->s_rtt = 0; } }
void ipxprotopr(u_long off, const char *name, int af1 __unused) { struct ipxpcb cb; struct ipxpcb *prev, *next; int isspx; if (off == 0) return; isspx = strcmp(name, "spx") == 0; kread(off, (char *)&cb, sizeof (struct ipxpcb)); ipxpcb = cb; prev = (struct ipxpcb *)off; if (ipxpcb.ipxp_next == (struct ipxpcb *)off) return; for (;ipxpcb.ipxp_next != (struct ipxpcb *)off; prev = next) { u_long ppcb; next = ipxpcb.ipxp_next; kread((u_long)next, (char *)&ipxpcb, sizeof (ipxpcb)); if (ipxpcb.ipxp_prev != prev) { printf("???\n"); break; } if (!aflag && ipx_nullhost(ipxpcb.ipxp_faddr) ) { continue; } kread((u_long)ipxpcb.ipxp_socket, (char *)&sockb, sizeof (sockb)); ppcb = (u_long) ipxpcb.ipxp_pcb; if (ppcb) { if (isspx) { kread(ppcb, (char *)&spxpcb, sizeof (spxpcb)); } else continue; } else if (isspx) continue; if (first) { printf("Active IPX connections"); if (aflag) printf(" (including servers)"); putchar('\n'); if (Aflag) printf("%-8.8s ", "PCB"); printf(Aflag ? "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" : "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n", "Proto", "Recv-Q", "Send-Q", "Local Address", "Foreign Address", "(state)"); first = 0; } if (Aflag) printf("%8lx ", ppcb); printf("%-5.5s %6u %6u ", name, sockb.so_rcv.sb_cc, sockb.so_snd.sb_cc); printf(Aflag?" %-18.18s":" %-22.22s", ipx_prpr(&ipxpcb.ipxp_laddr)); printf(Aflag?" %-18.18s":" %-22.22s", ipx_prpr(&ipxpcb.ipxp_faddr)); if (isspx) { extern char *tcpstates[]; if (spxpcb.s_state >= TCP_NSTATES) printf(" %d", spxpcb.s_state); else printf(" %s", tcpstates[spxpcb.s_state]); } putchar('\n'); prev = next; } }