📄 ldl.c
字号:
skb->len) ; if (alldata) cnt = skb->tail - skb->head ; /* dump everything in the buffer */ else alldata = cnt = 64 ; /* make alldata non-zero */ ldl_bfr_dump("Dump from skb->head", skb->head, cnt, alldata) ;#undef L}STATIC char *ldl_framing_type(unsigned long framing){ switch (framing & LDL_FRAME_MASK) { case LDL_FRAME_EII: return("LDL_FRAME_EII"); case LDL_FRAME_802_2: return("LDL_FRAME_802_2"); case LDL_FRAME_SNAP: return("LDL_FRAME_SNAP"); case LDL_FRAME_802_3: return("LDL_FRAME_802_3"); case LDL_FRAME_RAW_LLC: return("LDL_FRAME_RAW_LLC"); } return("LDL_FRAME_UNKNOWN");}STATIC char *ldl_pkt_type(unsigned saptype){ switch (saptype) {#ifdef ETH_P_ECHO case ETH_P_ECHO: return("ETH_P_ECHO");#endif case ETH_P_PUP: return("ETH_P_PUP"); case ETH_P_IP: return("ETH_P_IP"); case ETH_P_X25: return("ETH_P_X25"); case ETH_P_ARP: return("ETH_P_ARP"); case ETH_P_BPQ: return("ETH_P_BPQ"); case ETH_P_DEC: return("ETH_P_DEC"); case ETH_P_DNA_DL: return("ETH_P_DNA_DL"); case ETH_P_DNA_RC: return("ETH_P_DNA_RC"); case ETH_P_DNA_RT: return("ETH_P_DNA_RT"); case ETH_P_LAT: return("ETH_P_LAT"); case ETH_P_DIAG: return("ETH_P_DIAG"); case ETH_P_CUST: return("ETH_P_CUST"); case ETH_P_SCA: return("ETH_P_SCA"); case ETH_P_RARP: return("ETH_P_RARP"); case ETH_P_ATALK: return("ETH_P_ATALK"); case ETH_P_AARP: return("ETH_P_AARP"); case ETH_P_IPX: return("ETH_P_IPX"); case ETH_P_IPV6: return("ETH_P_IPV6"); case ETH_P_802_3: return("ETH_P_802_3"); case ETH_P_AX25: return("ETH_P_AX25"); case ETH_P_ALL: return("ETH_P_ALL"); case ETH_P_802_2: return("ETH_P_802_2"); case ETH_P_SNAP: return("ETH_P_SNAP"); case ETH_P_DDCMP: return("ETH_P_DDCMP"); case ETH_P_WAN_PPP: return("ETH_P_WAN_PPP"); case ETH_P_PPP_MP: return("ETH_P_PPP_MP"); case ETH_P_LOCALTALK:return("ETH_P_LOCALTALK"); case ETH_P_PPPTALK: return("ETH_P_PPPTALK"); case ETH_P_TR_802_2:return("ETH_P_TR_802_2"); case ETH_P_MOBITEX: return("ETH_P_MOBITEX"); case ETH_P_CONTROL: return("ETH_P_CONTROL"); case ETH_P_IRDA: return("ETH_P_IRDA"); case 0: return("NULL(0)"); } return("ETH_P_UNKNOWN");}void ldl_init(void){ if (initialized) return; printk("ldl: Linux streams datalink driver\n"); printk("ldl: Copyright (C) 1998 Ole Husgaard\n"); memset(dl_dl, 0, sizeof dl_dl); first_pt = NULL; first_ndev = NULL; first_open = NULL; n_hangup = 0; lis_spin_lock_init(&first_pt_lock, "LiS DLPI packet type list lock"); lis_spin_lock_init(&first_open_lock, "LiS DLPI open driver list lock"); initialized = 1;}/****************************************************************************//* *//* Packet type and SAP handling. *//* *//****************************************************************************//* * sap_create - create and add another packet type (sap) to a device. * * Returns 0 on success, -1 on failure. * * Notice that sap_create is always called under SPLSTR() */STATIC int sap_create(struct dl *dl, sap_t dlsap, dl_ushort saptype){ struct pt *pt, *npt; struct sap *sap; ASSERT(dl != NULL); ASSERT(dl->magic == DL_MAGIC); ASSERT(dl->ndev != NULL); saptype = htons(saptype); if ((sap = ALLOC(sizeof *sap)) == NULL) return -1; ++sap_n_alloc; memset(sap, 0, sizeof *sap); sap->magic = SAP_MAGIC; sap->dl = dl; sap->sap = dlsap; if (dl->sap == NULL) { /* This is a primary bind */ sap->next_sap = NULL; dl->sap = sap; } else { /* This is a subsequent bind */ sap->next_sap = dl->subs; dl->subs = sap; } /* Does Linux already pass us this packet type on this device? */ npt = NULL; lis_spin_lock(&first_pt_lock); do { for (pt = first_pt; pt; pt = pt->next) if (pt->pt.type == saptype && pt->pt.dev == dl->ndev->dev) break; if (pt == NULL) { if (npt == NULL) { lis_spin_unlock(&first_pt_lock); if ((npt = ALLOC(sizeof *pt)) == NULL) { FREE(sap); sap_n_alloc--; return -1; } ++pt_n_alloc; memset(npt, 0, sizeof *npt); lis_spin_lock(&first_pt_lock); } else { npt->next = first_pt; first_pt = pt = npt; } } else if (npt != NULL) { FREE(npt); npt = NULL; pt_n_alloc--; } } while (pt == NULL); sap->pt = pt; if (pt->listen == NULL) { /* New, unused packet_type */ ASSERT(pt->magic == 0); /* No need to synchronize with rcv_func() */ sap->next_listen = pt->listen; pt->listen = sap; lis_rw_lock_init(&pt->lock, "LiS SAP listening list"); pt->magic = PT_MAGIC; pt->pt.type = saptype; pt->pt.dev = dl->ndev->dev; pt->pt.func = rcv_func; pt->pt.data = NULL; pt->pt.next = NULL; lis_spin_unlock(&first_pt_lock); dev_add_pack(&pt->pt); } else { /* Re-use of packet_type */ ASSERT(pt->magic == PT_MAGIC); ASSERT(pt->pt.type == saptype); ASSERT(pt->pt.func == rcv_func); lis_rw_write_lock(&pt->lock); sap->next_listen = pt->listen; pt->listen = sap; lis_rw_write_unlock(&pt->lock); lis_spin_unlock(&first_pt_lock); } return 0;}/* * sap_destroy - remove and destroy a packet type (sap) from a device. * * Returns 0 on success, -1 if not found. */STATIC int sap_destroy(struct dl *dl, struct sap *sap){ int psw; struct pt *pt, *opt; struct sap **sapp_dl, **sapp_pt; ASSERT(dl != NULL); ASSERT(dl->magic == DL_MAGIC); ASSERT(sap != NULL); ASSERT(sap->magic == SAP_MAGIC); ASSERT(dl->subs != NULL || sap == dl->sap); pt = sap->pt; ASSERT(pt != NULL); ASSERT(pt->magic == PT_MAGIC); SPLSTR(psw); lis_spin_lock(&first_pt_lock); lis_rw_write_lock(&pt->lock); if (pt->listen == sap && sap->next_listen == NULL) { /* It is the last use of this packet_type */ lis_rw_write_unlock(&pt->lock); if (pt == first_pt) first_pt = pt->next; else { for (opt = first_pt; opt->next != NULL; opt = opt->next) if (opt->next == pt) { opt->next = pt->next; break; } } lis_spin_unlock(&first_pt_lock); dev_remove_pack(&pt->pt); pt->magic = 0; FREE(pt); --pt_n_alloc; } else { lis_spin_unlock(&first_pt_lock); sapp_pt = &pt->listen; for (;;) { ASSERT(*sapp_pt != NULL); if (*sapp_pt == NULL) { /* * Not found, but it should be there: * Emergency brake */ lis_rw_write_unlock(&pt->lock); SPLX(psw); return -1; } if (*sapp_pt == sap) break; sapp_pt = &(*sapp_pt)->next_listen; } *sapp_pt = sap->next_listen; lis_rw_write_unlock(&pt->lock); } if (dl->sap == sap) { ASSERT(dl->subs == NULL); dl->sap = NULL; } else { sapp_dl = &dl->subs; for(;;) { ASSERT(*sapp_dl != NULL); if (*sapp_dl == NULL) { /* * Not found, but it should be there: * Emergency brake */ SPLX(psw); return -1; } ASSERT((*sapp_dl)->magic == SAP_MAGIC); ASSERT((*sapp_dl)->dl == dl); if (*sapp_dl == sap) break; sapp_dl = &(*sapp_dl)->next_sap; } *sapp_dl = sap->next_sap; } sap->dl = NULL; sap->pt = NULL; sap->magic = 0; FREE(sap); --sap_n_alloc; SPLX(psw); return 0;}/* * sap_destroy_all - remove and destroy all packet types (sap) from a device. */STATIC void sap_destroy_all(struct dl *dl){ int ret; ASSERT(dl != NULL); while (dl->subs) { ASSERT(dl->subs->pt != NULL); ret = sap_destroy(dl, dl->subs); ASSERT(ret == 0); if (ret != 0) return; /* Emergency brake */ } if (dl->sap) { ASSERT(dl->sap->pt != NULL); ret = sap_destroy(dl, dl->sap); ASSERT(ret == 0); }}/****************************************************************************//* *//* Hangup handling. *//* *//****************************************************************************//* * hangup_set - set endpoint flag for hangup * * Not reentrant. */STATIC INLINE void hangup_set(struct dl *dl){ if ((dl->flags & LDLFLAG_HANGUP) == 0) { /* * A hangup should never happen on an unattached device. */ ASSERT(dl->dlstate != DL_UNATTACHED); /* * The hangup has not already been done. */ ASSERT((dl->flags & LDLFLAG_HANGUP_DONE) != 0); /* * This endpoint should already have been disassociated * from the netdevice. */ ASSERT(dl->ndev == NULL); dl->flags |= LDLFLAG_HANGUP; /* Set flag */ ++n_hangup; /* Update count */ }}/* * hangup_do - do the actual hangup on an endpoint */STATIC INLINE void hangup_do(struct dl *dl){ int psw; SPLSTR(psw); ASSERT((dl->flags & LDLFLAG_HANGUP) != 0); /* Has the hangup been done already? */ if ((dl->flags & LDLFLAG_HANGUP_DONE) != 0) { SPLX(psw); return; } ASSERT(n_hangup > 0); /* * In the transient states a hangup cannot easily be done. * A check of the hangup flag retries the hangup when these states * are left. */ if (dl->dlstate == DL_UNBIND_PENDING || dl->dlstate == DL_SUBS_UNBIND_PND) { SPLX(psw); return; } /* * Go into the DL_UNATTACHED state before hanging up. * This ensures that all resources associated with the endpoint * are released. In particular, no more unitdata indications * should come from this endpoint. */ if (dl->dlstate == DL_IDLE) { sap_destroy_all(dl); dl->dlstate = DL_UNBOUND; } if (dl->dlstate == DL_UNBOUND) { STATIC void ndev_release(struct dl *dl); ndev_release(dl); dl->addr_len = 0; dl->ndev = NULL; dl->dlstate = DL_UNATTACHED; } ASSERT(dl->dlstate == DL_UNATTACHED); SPLX(psw); if (putctl(dl->rq->q_next, M_HANGUP)) { SPLSTR(psw); if ((dl->flags & LDLFLAG_HANGUP_DONE) == 0) { dl->flags |= LDLFLAG_HANGUP_DONE; --n_hangup; } SPLX(psw); } else printk("ldl: cannot send M_HANGUP\n");}/****************************************************************************//* *//* Netdevice handling. *//* *//****************************************************************************//* * ndev_find - find netdevice * * Not reentrant, returns NULL if not found. */STATIC INLINE struct ndev *ndev_find(struct ldldev *dev){ struct ndev *ndev; for (ndev = first_ndev; ndev; ndev = ndev->next) if (ndev->dev == dev) break; return ndev;}/* * ndev_get - create or find netdevice * * Not reentrant, returns NULL on failure. */STATIC struct ndev *ndev_get(dl_ulong ppa){ dl_ulong i; struct ldldev *dev; struct ndev *ndev; /* Find the Linux netdevice to attach to */ for (dev = dev_base, i = 0; dev; dev = dev->next, ++i) if (ppa == i) break; if (dev == NULL) return NULL; ASSERT(ppa == i); if ((ndev = ndev_find(dev)) == NULL) { if ((ndev = ALLOC(sizeof *ndev)) == NULL) return NULL; ++ndev_n_alloc; memset(ndev, 0, sizeof *ndev); ndev->magic = NDEV_MAGIC; ndev->dev = dev; ndev->wr_max = DEV_WR_MAX; ndev->wr_min = DEV_WR_MIN; } return ndev;}/* * ndev_attach - attach endpoint to a netdevice * * Not reentrant. */STATIC void ndev_attach(struct ndev *ndev, struct dl *dl){ ASSERT(ndev != NULL); ASSERT(ndev->magic == NDEV_MAGIC); ASSERT(dl != NULL); ASSERT(dl->magic == DL_MAGIC); ASSERT(dl->ndev == NULL); dl->ndev = ndev; dl->next_ndev = ndev->endpoints; ndev->endpoints = dl;}/* * ndev_free - free netdevice * * Not reentrant.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -