📄 qif.c
字号:
qif_t *qif;queue_t *q;{ packet_filter_hook_t *pfh; qif_t **qp; int rm = 0; if (qif == NULL) return; WRITE_ENTER(&pfil_rw); PT_ENTER_WRITE(&qif->qf_ptl); if (qif->qf_bound == 1 && qif_verbose > 0) cmn_err(CE_NOTE, "PFIL: detaching [%s] - %s", qif->qf_name, SAPNAME(qif)); for (qp = &qif_head; *qp; qp = &(*qp)->qf_next) if (*qp == qif) { *qp = qif->qf_next; rm = 1; break; } PT_EXIT_WRITE(&qif->qf_ptl); RW_EXIT(&pfil_rw); if (qif->qf_ill) { READ_ENTER(&pfh_sync.ph_lock); pfh = pfil_hook_get(PFIL_OUT, &pfh_sync); for (; pfh; pfh = pfh->pfil_next) if (pfh->pfil_func) (void) (*pfh->pfil_func)(NULL, 0, qif, 1, qif, NULL); RW_EXIT(&pfh_sync.ph_lock); } if (rm) { mutex_destroy(&qif->qf_ptl.pt_lock); cv_destroy(&qif->qf_ptl.pt_cv); if (qif->qf_qifsz == sizeof(*qif)) kmem_cache_free(qif_cache, qif); else { KMFREE(qif, qif->qf_qifsz); } } return;}/* ------------------------------------------------------------------------ *//* Function: qif_iflookup *//* Returns: void * - NULL == search failed, else pointer to qif_t *//* Parameters: name(I) - pointer to the name *//* sap(I) - SAP value *//* Locks: pfil_rw *//* *//* Search the list of registered qif_t's for a match based on the name and *//* the SAP and return a pointer to the matching entry. *//* ------------------------------------------------------------------------ */void *qif_iflookup(char *name, int sap){ qif_t *qif; for (qif = qif_head; qif; qif = qif->qf_next) if ((!sap || (qif->qf_sap == sap)) && !strcmp(qif->qf_name, name)) break; return qif;}/* ------------------------------------------------------------------------ *//* Function: qif_update *//* Returns: void *//* Parameters: qif(I) - pointer to qif_t structure *//* mp(I) - pointer to STREAMS message *//* Locks: pfil_rw *//* *//* This function attempts to force an update of the qf_sap and qf_hl fields *//* using information that is in the STREAMS message and/or the ill_t. This *//* function should only be called if the mblk is a DL_IOC_HDR_INFO message. *//* ------------------------------------------------------------------------ */void qif_update(qif, mp)qif_t *qif;mblk_t *mp;{ ill_t *ill; ill = qif->qf_ill; if (ill == NULL) return; if (mp->b_datap->db_type == M_IOCACK && mp->b_cont) { mp = mp->b_cont; if (mp->b_datap->db_type == M_PROTO && mp->b_cont) { mp = mp->b_cont; if (mp->b_datap->db_type == M_DATA) { qif->qf_hl = mp->b_wptr - mp->b_rptr; } } } /* * If we still have a 0 size expected fasthpath header length, check * the ill structure to see if we can use it to now make a better * guess about what to use. */ qif->qf_sap = ill->ill_sap; if (qif->qf_hl == 0) {#if SOLARIS2 < 8 qif->qf_hl = ill->ill_hdr_length;#else if ((ill->ill_type > 0) && (ill->ill_type < 0x37) && (hdrsizes[ill->ill_type][0] == ill->ill_type)) qif->qf_hl = hdrsizes[ill->ill_type][1];#endif }}/* ------------------------------------------------------------------------ *//* Function: qif_walk *//* Returns: qif_t * - NULL == search failed, else pointer to qif_t *//* Parameters: qfp(IO) - pointer to the name *//* *//* NOTE: it is assumed the caller has a lock on pfil_rw *//* *//* Provide a function to enable the caller to enumerate through all of the *//* qif_t's without being aware of the internal data structure used to store *//* them in. *//* ------------------------------------------------------------------------ */qif_t *qif_walk(qif_t **qfp){ struct qif *qf, *qf2; if (qfp == NULL) return NULL; qf = *qfp; if (qf == NULL) *qfp = qif_head; else { /* * Make sure the pointer being passed in exists as a current * object before returning its next value. */ for (qf2 = qif_head; qf2 != NULL; qf2 = qf2->qf_next) if (qf2 == qf) break; if (qf2 == NULL) *qfp = NULL; else *qfp = qf->qf_next; } return *qfp;}/* ------------------------------------------------------------------------ *//* Function: qif_ipmp_update *//* Returns: void *//* Parameters: ipmpconf(I) - pointer to an ill to match against *//* *//* Take an IPMP configuration string passed in to update the pfil config. *//* The string may either indicate that an IPMP interface is to be deleted *//* ("ipmp0=" - no NICs after the right of the '=') or created/changed if *//* there is text after the '='. *//* ------------------------------------------------------------------------ */void qif_ipmp_update(char *ipmpconf){ qif_t *qif, *qf; int len, sap; char *s; sap = ETHERTYPE_IP; if (!strncmp(ipmpconf, "v4:", 3)) { ipmpconf += 3; } else if (!strncmp(ipmpconf, "v6:", 3)) {#if SOLARIS2 >= 8 sap = IP6_DL_SAP; ipmpconf += 3;#else return;#endif } s = strchr(ipmpconf, '='); if (s != NULL) { if (*(s + 1) == '\0') *s = '\0'; else *s++ = '\0'; } if (s == NULL || *s == NULL) { qif_ipmp_delete(ipmpconf); return; } len = sizeof(qif_t) + strlen(s) + 1; KMALLOC(qif, qif_t *, len, KM_NOSLEEP); if (qif == NULL) { cmn_err(CE_NOTE, "PFIL: malloc(%ld) for qif_t failed", len); return; } WRITE_ENTER(&pfil_rw); for (qf = qif_head; qf; qf = qf->qf_next) if (strcmp(qf->qf_name, ipmpconf) == 0) break; if (qf == NULL) { qf = qif; qif->qf_next = qif_head; qif_head = qif; qif->qf_sap = sap; qif->qf_flags |= QF_IPMP; qif->qf_qifsz = len; qif->qf_members = (char *)qif + sizeof(*qif); strcpy(qif->qf_name, ipmpconf); } else { KMFREE(qif, len); qif = qf; } strcpy(qif->qf_members, s); qif_ipmp_syncmaster(qif, sap); RW_EXIT(&pfil_rw);}/* ------------------------------------------------------------------------ *//* Function: qif_ipmp_delete *//* Returns: void *//* Parameters: qifname(I) - pointer to name of qif to delete *//* *//* Search for a qif structure that is named to match qifname, remove all *//* references to it by others, delink and free it. *//* ------------------------------------------------------------------------ */void qif_ipmp_delete(char *qifname){ packet_filter_hook_t *pfh; qif_t *qf, **qfp, *qif; WRITE_ENTER(&pfil_rw); for (qfp = &qif_head; (qif = *qfp) != NULL; qfp = &qif->qf_next) { if ((qif->qf_flags & QF_IPMP) == 0) continue; if (strcmp(qif->qf_name, qifname) == 0) { *qfp = qif->qf_next; for (qf = qif_head; qf != NULL; qf = qf->qf_next) if (qf->qf_ipmp == qif) qf->qf_ipmp = NULL; break; } } RW_EXIT(&pfil_rw); if (qif != NULL) { pfh = pfil_hook_get(PFIL_OUT, &pfh_sync); for (; pfh; pfh = pfh->pfil_next) if (pfh->pfil_func) (void) (*pfh->pfil_func)(NULL, 0, qif, 1, qif, NULL); KMFREE(qif, qif->qf_qifsz); }}/* ------------------------------------------------------------------------ *//* Function: qif_ipmp_syncmaster *//* Returns: void *//* Parameters: updated(I) - pointer to updated qif structure *//* Locks: pfil_rw *//* *//* This function rechecks all the qif structures that aren't defined for *//* IPMP to see if they are indeed members of the group pointed to by *//* updated. Ones that currently claim to be in updated are reset and *//* rechecked in case they have become excluded. This function should be *//* called for any new IPMP qif's created or when an IPMP qif changes. *//* ------------------------------------------------------------------------ */void qif_ipmp_syncmaster(qif_t *updated, const int sap){ char *s, *t; qif_t *qf; for (qf = qif_head; qf != NULL; qf = qf->qf_next) { if ((qf->qf_flags & QF_IPMP) != 0) continue; if (qf->qf_sap != sap) continue; if (qf->qf_ipmp == updated) qf->qf_ipmp = NULL; for (s = updated->qf_members; s != NULL; ) { t = strchr(s, ','); if (t != NULL) *t = '\0'; if (strcmp(qf->qf_name, s) == 0) qf->qf_ipmp = updated; if (t != NULL) *t++ = ','; s = t; } }}/* ------------------------------------------------------------------------ *//* Function: qif_ipmp_syncslave *//* Returns: void *//* Parameters: target(I) - pointer to updated qif structure *//* Locks: pfil_rw *//* *//* Check through the list of qif's to see if there is an IPMP with a member *//* list that includes the one named by target. *//* ------------------------------------------------------------------------ */void qif_ipmp_syncslave(qif_t *target, const int sap){ char *s, *t; qif_t *qf; target->qf_ipmp = NULL; /* * Recheck the entire list of qif's for any references to the one * we have just created/updated (updated). */ for (qf = qif_head; qf != NULL; qf = qf->qf_next) { if ((qf->qf_flags & QF_IPMP) == 0) continue; if (qf->qf_sap != sap) continue; for (s = qf->qf_members; s != NULL; ) { t = strchr(s, ','); if (t != NULL) *t = '\0'; if (strcmp(target->qf_name, s) == 0) target->qf_ipmp = qf; if (t != NULL) *t++ = ','; s = t; if (target->qf_ipmp == qf) break; } }}/* ------------------------------------------------------------------------ *//* Function: qif_hl_set *//* Returns: void *//* Parameters: ipmpconf(I) - string with header length setting for NIC *//* *//* For NICs that we cannot automatically determine the MAC header length of *//* we provide a manual crook to achieve that with. The input syntax for *//* the string is "[v4:|v6:]<ifname>=<length>" *//* ------------------------------------------------------------------------ */void qif_hl_set(char *ipmpconf){ qif_t *qif, *qf; int len, sap; char *s; sap = ETHERTYPE_IP; if (!strncmp(ipmpconf, "v4:", 3)) { ipmpconf += 3; } else if (!strncmp(ipmpconf, "v6:", 3)) {#if SOLARIS2 >= 8 sap = IP6_DL_SAP; ipmpconf += 3;#else return;#endif } s = strchr(ipmpconf, '='); if (s != NULL) { if (*(s + 1) == '\0') *s = '\0'; else *s++ = '\0'; } if (s == NULL || *s == NULL) return; READ_ENTER(&pfil_rw); for (qf = qif_head; qf; qf = qf->qf_next) if (strcmp(qf->qf_name, ipmpconf) == 0) break; if (qf != NULL) { int hl = 0; for (; *s != '\0'; s++) { char c = *s; if (c < '0' || c > '9') return; hl *= 10; hl += c - '0'; } qf->qf_hl = hl; } RW_EXIT(&pfil_rw);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -