/* * Partition an mbuf chain in two pieces, returning the tail -- * all but the first len0 bytes. In case of failure, it returns NULL and * attempts to restore the chain to its original state. */ struct mbuf * m_split(struct mbuf *m0, int len0, int wait) { struct mbuf *m, *n; unsigned len = len0, remain, olen; for (m = m0; m && len > m->m_len; m = m->m_next) len -= m->m_len; if (m == NULL) return (NULL); remain = m->m_len - len; if (m0->m_flags & M_PKTHDR) { MGETHDR(n, wait, m0->m_type); if (n == NULL) return (NULL); if (m_dup_pkthdr(n, m0, wait)) { m_freem(n); return (NULL); } n->m_pkthdr.len -= len0; olen = m0->m_pkthdr.len; m0->m_pkthdr.len = len0; if (m->m_flags & M_EXT) goto extpacket; if (remain > MHLEN) { /* m can't be the lead packet */ MH_ALIGN(n, 0); n->m_next = m_split(m, len, wait); if (n->m_next == NULL) { (void) m_free(n); m0->m_pkthdr.len = olen; return (NULL); } else return (n); } else MH_ALIGN(n, remain); } else if (remain == 0) { n = m->m_next; m->m_next = NULL; return (n); } else { MGET(n, wait, m->m_type); if (n == NULL) return (NULL); M_ALIGN(n, remain); } extpacket: if (m->m_flags & M_EXT) { n->m_ext = m->m_ext; MCLADDREFERENCE(m, n); n->m_data = m->m_data + len; } else { memcpy(mtod(n, caddr_t), mtod(m, caddr_t) + len, remain); } n->m_len = remain; m->m_len = len; n->m_next = m->m_next; m->m_next = NULL; return (n); }
static int analyse(char *line, t_env *e, int i) { char **str_p; char **str; int nb; if (line) { str = m_split(line); str_p = ft_strsplit(line, ' '); } if (i == 0) { nb = ft_atoi(line); if (nb < 0) return (-1); e->worms = nb; return (1); } else if (line && ft_strcmp(line, "##start") == 0 && e->start == 0) return (e->start = 1); else if (line && ft_strcmp(line, "##end") == 0 && e->end == 0) return (e->end = 1); else if (line && line[0] == '#' && (ft_strcmp(line, "##start") != 0 || ft_strcmp(line, "##end") != 0)) return (free_tab(&str, &str_p, 1)); return (analyse2(line, str, str_p, e)); }
errno_t mbuf_split(mbuf_t src, size_t offset, mbuf_how_t how, mbuf_t *new_mbuf) { /* Must set *new_mbuf to NULL in failure case */ *new_mbuf = m_split(src, offset, how); return (*new_mbuf == NULL ? ENOMEM : 0); }
static int smb_t2_placedata(struct mbuf *mtop, u_int16_t offset, u_int16_t count, struct mdchain *mdp) { struct mbuf *m, *m0; int len; m0 = m_split(mtop, offset, M_WAIT); len = m_length(m0, &m); m->m_len -= len - count; if (mdp->md_top == NULL) { md_initm(mdp, m0); } else m_cat(mdp->md_top, m0); return 0; }
static int parse_key_value_pair(char* pair, char* key, char* value) { if(pair == NULL || key == NULL || value == NULL) return -1; char** toks; int num_toks; int i; toks = m_split(pair, ":", PARSERULE_SIZE, &num_toks, 0); if(toks[0] == NULL || toks[1] == NULL) { m_split_free(&toks, num_toks); return -1; } else { char* p_start, *p_end; char tmp[2][PARSERULE_SIZE]={{0}, {0}}; for(i=0; i<2; i++) { p_start = toks[i]; p_end = toks[i]+strlen(toks[i])-1; if(*p_start=='"') p_start++; if(*p_end=='"') *p_end = 0x00; strcpy(tmp[i], p_start); } strcpy(key, tmp[0]); strcpy(value, tmp[1]); m_split_free(&toks, num_toks); } return 0; }
static int smb_t2_placedata(struct mbuf *mtop, u_int16_t offset, u_int16_t count, struct mdchain *mdp) { struct mbuf *m, *m0; int len; m0 = m_split(mtop, offset, M_WAIT); if (m0 == NULL) return EBADRPC; for(len = 0, m = m0; m->m_next; m = m->m_next) len += m->m_len; len += m->m_len; m->m_len -= len - count; if (mdp->md_top == NULL) { md_initm(mdp, m0); } else m_cat(mdp->md_top, m0); return 0; }
static bool_t svc_vc_recv(SVCXPRT *xprt, struct rpc_msg *msg, struct sockaddr **addrp, struct mbuf **mp) { struct cf_conn *cd = (struct cf_conn *) xprt->xp_p1; struct uio uio; struct mbuf *m; XDR xdrs; int error, rcvflag; /* * Serialise access to the socket and our own record parsing * state. */ sx_xlock(&xprt->xp_lock); for (;;) { /* * If we have an mbuf chain in cd->mpending, try to parse a * record from it, leaving the result in cd->mreq. If we don't * have a complete record, leave the partial result in * cd->mreq and try to read more from the socket. */ if (cd->mpending) { /* * If cd->resid is non-zero, we have part of the * record already, otherwise we are expecting a record * marker. */ if (!cd->resid) { /* * See if there is enough data buffered to * make up a record marker. Make sure we can * handle the case where the record marker is * split across more than one mbuf. */ size_t n = 0; uint32_t header; m = cd->mpending; while (n < sizeof(uint32_t) && m) { n += m->m_len; m = m->m_next; } if (n < sizeof(uint32_t)) goto readmore; if (cd->mpending->m_len < sizeof(uint32_t)) cd->mpending = m_pullup(cd->mpending, sizeof(uint32_t)); memcpy(&header, mtod(cd->mpending, uint32_t *), sizeof(header)); header = ntohl(header); cd->eor = (header & 0x80000000) != 0; cd->resid = header & 0x7fffffff; m_adj(cd->mpending, sizeof(uint32_t)); } /* * Start pulling off mbufs from cd->mpending * until we either have a complete record or * we run out of data. We use m_split to pull * data - it will pull as much as possible and * split the last mbuf if necessary. */ while (cd->mpending && cd->resid) { m = cd->mpending; if (cd->mpending->m_next || cd->mpending->m_len > cd->resid) cd->mpending = m_split(cd->mpending, cd->resid, M_WAIT); else cd->mpending = NULL; if (cd->mreq) m_last(cd->mreq)->m_next = m; else cd->mreq = m; while (m) { cd->resid -= m->m_len; m = m->m_next; } } /* * If cd->resid is zero now, we have managed to * receive a record fragment from the stream. Check * for the end-of-record mark to see if we need more. */ if (cd->resid == 0) { if (!cd->eor) continue; /* * Success - we have a complete record in * cd->mreq. */ xdrmbuf_create(&xdrs, cd->mreq, XDR_DECODE); cd->mreq = NULL; sx_xunlock(&xprt->xp_lock); if (! xdr_callmsg(&xdrs, msg)) { XDR_DESTROY(&xdrs); return (FALSE); } *addrp = NULL; *mp = xdrmbuf_getall(&xdrs); XDR_DESTROY(&xdrs); return (TRUE); } } readmore: /* * The socket upcall calls xprt_active() which will eventually * cause the server to call us here. We attempt to * read as much as possible from the socket and put * the result in cd->mpending. If the read fails, * we have drained both cd->mpending and the socket so * we can call xprt_inactive(). */ uio.uio_resid = 1000000000; uio.uio_td = curthread; m = NULL; rcvflag = MSG_DONTWAIT; CURVNET_SET(xprt->xp_socket->so_vnet); error = soreceive(xprt->xp_socket, NULL, &uio, &m, NULL, &rcvflag); CURVNET_RESTORE(); if (error == EWOULDBLOCK) { /* * We must re-test for readability after * taking the lock to protect us in the case * where a new packet arrives on the socket * after our call to soreceive fails with * EWOULDBLOCK. The pool lock protects us from * racing the upcall after our soreadable() * call returns false. */ mtx_lock(&xprt->xp_pool->sp_lock); if (!soreadable(xprt->xp_socket)) xprt_inactive_locked(xprt); mtx_unlock(&xprt->xp_pool->sp_lock); sx_xunlock(&xprt->xp_lock); return (FALSE); } if (error) { SOCKBUF_LOCK(&xprt->xp_socket->so_rcv); if (xprt->xp_upcallset) { xprt->xp_upcallset = 0; soupcall_clear(xprt->xp_socket, SO_RCV); } SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv); xprt_inactive(xprt); cd->strm_stat = XPRT_DIED; sx_xunlock(&xprt->xp_lock); return (FALSE); } if (!m) { /* * EOF - the other end has closed the socket. */ xprt_inactive(xprt); cd->strm_stat = XPRT_DIED; sx_xunlock(&xprt->xp_lock); return (FALSE); } if (cd->mpending) m_last(cd->mpending)->m_next = m; else cd->mpending = m; }
/* * Partition an mbuf chain in two pieces, returning the tail -- * all but the first len0 bytes. In case of failure, it returns NULL and * attempts to restore the chain to its original state. * * Note that the resulting mbufs might be read-only, because the new * mbuf can end up sharing an mbuf cluster with the original mbuf if * the "breaking point" happens to lie within a cluster mbuf. Use the * M_WRITABLE() macro to check for this case. */ struct mbuf * m_split(struct mbuf *m0, int len0, int wait) { struct mbuf *m, *n; u_int len = len0, remain; MBUF_CHECKSLEEP(wait); for (m = m0; m && len > m->m_len; m = m->m_next) len -= m->m_len; if (m == NULL) return (NULL); remain = m->m_len - len; if (m0->m_flags & M_PKTHDR && remain == 0) { n = m_gethdr(wait, m0->m_type); if (n == NULL) return (NULL); n->m_next = m->m_next; m->m_next = NULL; n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif; n->m_pkthdr.len = m0->m_pkthdr.len - len0; m0->m_pkthdr.len = len0; return (n); } else if (m0->m_flags & M_PKTHDR) { n = m_gethdr(wait, m0->m_type); if (n == NULL) return (NULL); n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif; n->m_pkthdr.len = m0->m_pkthdr.len - len0; m0->m_pkthdr.len = len0; if (m->m_flags & M_EXT) goto extpacket; if (remain > MHLEN) { /* m can't be the lead packet */ M_ALIGN(n, 0); n->m_next = m_split(m, len, wait); if (n->m_next == NULL) { (void) m_free(n); return (NULL); } else { n->m_len = 0; return (n); } } else M_ALIGN(n, remain); } else if (remain == 0) { n = m->m_next; m->m_next = NULL; return (n); } else { n = m_get(wait, m->m_type); if (n == NULL) return (NULL); M_ALIGN(n, remain); } extpacket: if (m->m_flags & M_EXT) { n->m_data = m->m_data + len; mb_dupcl(n, m); } else { bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain); } n->m_len = remain; m->m_len = len; n->m_next = m->m_next; m->m_next = NULL; return (n); }
int ng_l2cap_lp_send(ng_l2cap_con_p con, u_int16_t dcid, struct mbuf *m0) { ng_l2cap_p l2cap = con->l2cap; ng_l2cap_hdr_t *l2cap_hdr = NULL; ng_hci_acldata_pkt_t *acl_hdr = NULL; struct mbuf *m_last = NULL, *m = NULL; int len, flag = NG_HCI_PACKET_START; KASSERT((con->tx_pkt == NULL), ("%s: %s - another packet pending?!\n", __func__, NG_NODE_NAME(l2cap->node))); KASSERT((l2cap->pkt_size > 0), ("%s: %s - invalid l2cap->pkt_size?!\n", __func__, NG_NODE_NAME(l2cap->node))); /* Prepend mbuf with L2CAP header */ m0 = ng_l2cap_prepend(m0, sizeof(*l2cap_hdr)); if (m0 == NULL) { NG_L2CAP_ALERT( "%s: %s - ng_l2cap_prepend(%zd) failed\n", __func__, NG_NODE_NAME(l2cap->node), sizeof(*l2cap_hdr)); goto fail; } l2cap_hdr = mtod(m0, ng_l2cap_hdr_t *); l2cap_hdr->length = htole16(m0->m_pkthdr.len - sizeof(*l2cap_hdr)); l2cap_hdr->dcid = htole16(dcid); /* * Segment single L2CAP packet according to the HCI layer MTU. Convert * each segment into ACL data packet and prepend it with ACL data packet * header. Link all segments together via m_nextpkt link. * * XXX BC (Broadcast flag) will always be 0 (zero). */ while (m0 != NULL) { /* Check length of the packet against HCI MTU */ len = m0->m_pkthdr.len; if (len > l2cap->pkt_size) { m = m_split(m0, l2cap->pkt_size, M_DONTWAIT); if (m == NULL) { NG_L2CAP_ALERT( "%s: %s - m_split(%d) failed\n", __func__, NG_NODE_NAME(l2cap->node), l2cap->pkt_size); goto fail; } len = l2cap->pkt_size; } /* Convert packet fragment into ACL data packet */ m0 = ng_l2cap_prepend(m0, sizeof(*acl_hdr)); if (m0 == NULL) { NG_L2CAP_ALERT( "%s: %s - ng_l2cap_prepend(%zd) failed\n", __func__, NG_NODE_NAME(l2cap->node), sizeof(*acl_hdr)); goto fail; } acl_hdr = mtod(m0, ng_hci_acldata_pkt_t *); acl_hdr->type = NG_HCI_ACL_DATA_PKT; acl_hdr->length = htole16(len); acl_hdr->con_handle = htole16(NG_HCI_MK_CON_HANDLE( con->con_handle, flag, 0)); /* Add fragment to the chain */ m0->m_nextpkt = NULL; if (con->tx_pkt == NULL) con->tx_pkt = m_last = m0; else { m_last->m_nextpkt = m0; m_last = m0; } NG_L2CAP_INFO( "%s: %s - attaching ACL packet, con_handle=%d, PB=%#x, length=%d\n", __func__, NG_NODE_NAME(l2cap->node), con->con_handle, flag, len); m0 = m; m = NULL; flag = NG_HCI_PACKET_FRAGMENT; } return (0); fail: NG_FREE_M(m0); NG_FREE_M(m); while (con->tx_pkt != NULL) { m = con->tx_pkt->m_nextpkt; m_freem(con->tx_pkt); con->tx_pkt = m; } return (ENOBUFS); } /* ng_l2cap_lp_send */
/* * If we have an mbuf chain in cd->mpending, try to parse a record from it, * leaving the result in cd->mreq. If we don't have a complete record, leave * the partial result in cd->mreq and try to read more from the socket. */ static int svc_vc_process_pending(SVCXPRT *xprt) { struct cf_conn *cd = (struct cf_conn *) xprt->xp_p1; struct socket *so = xprt->xp_socket; struct mbuf *m; /* * If cd->resid is non-zero, we have part of the * record already, otherwise we are expecting a record * marker. */ if (!cd->resid && cd->mpending) { /* * See if there is enough data buffered to * make up a record marker. Make sure we can * handle the case where the record marker is * split across more than one mbuf. */ size_t n = 0; uint32_t header; m = cd->mpending; while (n < sizeof(uint32_t) && m) { n += m->m_len; m = m->m_next; } if (n < sizeof(uint32_t)) { so->so_rcv.sb_lowat = sizeof(uint32_t) - n; return (FALSE); } m_copydata(cd->mpending, 0, sizeof(header), (char *)&header); header = ntohl(header); cd->eor = (header & 0x80000000) != 0; cd->resid = header & 0x7fffffff; m_adj(cd->mpending, sizeof(uint32_t)); } /* * Start pulling off mbufs from cd->mpending * until we either have a complete record or * we run out of data. We use m_split to pull * data - it will pull as much as possible and * split the last mbuf if necessary. */ while (cd->mpending && cd->resid) { m = cd->mpending; if (cd->mpending->m_next || cd->mpending->m_len > cd->resid) cd->mpending = m_split(cd->mpending, cd->resid, M_WAITOK); else cd->mpending = NULL; if (cd->mreq) m_last(cd->mreq)->m_next = m; else cd->mreq = m; while (m) { cd->resid -= m->m_len; m = m->m_next; } } /* * Block receive upcalls if we have more data pending, * otherwise report our need. */ if (cd->mpending) so->so_rcv.sb_lowat = INT_MAX; else so->so_rcv.sb_lowat = imax(1, imin(cd->resid, so->so_rcv.sb_hiwat / 2)); return (TRUE); }
bool_t xdr_rpc_gss_unwrap_data(struct mbuf **resultsp, gss_ctx_id_t ctx, gss_qop_t qop, rpc_gss_service_t svc, u_int seq) { struct mbuf *results, *message, *mic; uint32_t len, cklen; OM_uint32 maj_stat, min_stat; u_int seq_num, conf_state, qop_state; results = *resultsp; *resultsp = NULL; message = NULL; if (svc == rpc_gss_svc_integrity) { /* * Extract the seq+message part. Remember that there * may be extra RPC padding in the checksum. The * message part is RPC encoded already so no * padding. */ len = get_uint32(&results); message = results; results = m_split(results, len, M_WAITOK); if (!results) { m_freem(message); return (FALSE); } /* * Extract the MIC and make it contiguous. */ cklen = get_uint32(&results); if (!results) { m_freem(message); return (FALSE); } KASSERT(cklen <= MHLEN, ("unexpected large GSS-API checksum")); mic = results; if (cklen > mic->m_len) { mic = m_pullup(mic, cklen); if (!mic) { m_freem(message); return (FALSE); } } if (cklen != RNDUP(cklen)) m_trim(mic, cklen); /* Verify checksum and QOP. */ maj_stat = gss_verify_mic_mbuf(&min_stat, ctx, message, mic, &qop_state); m_freem(mic); if (maj_stat != GSS_S_COMPLETE || qop_state != qop) { m_freem(message); rpc_gss_log_status("gss_verify_mic", NULL, maj_stat, min_stat); return (FALSE); } } else if (svc == rpc_gss_svc_privacy) { /* Decode databody_priv. */ len = get_uint32(&results); if (!results) return (FALSE); /* Decrypt databody. */ message = results; if (len != RNDUP(len)) m_trim(message, len); maj_stat = gss_unwrap_mbuf(&min_stat, ctx, &message, &conf_state, &qop_state); /* Verify encryption and QOP. */ if (maj_stat != GSS_S_COMPLETE) { rpc_gss_log_status("gss_unwrap", NULL, maj_stat, min_stat); return (FALSE); } if (qop_state != qop || conf_state != TRUE) { m_freem(results); return (FALSE); } } /* Decode rpc_gss_data_t (sequence number + arguments). */ seq_num = get_uint32(&message); if (!message) return (FALSE); /* Verify sequence number. */ if (seq_num != seq) { rpc_gss_log_debug("wrong sequence number in databody"); m_freem(message); return (FALSE); } *resultsp = message; return (TRUE); }
int parse_rule_content(char* rule) { if(rule == NULL) return -1; char* index = rule; char** toks; int i; // j; int num_toks; // int ruletype; int level; rule_node_t rule_node[10]; //每一行内容可能包含多个content int rule_num = 0; memset(&rule_node, 0, sizeof(rule_node_t)*10); while(*index == ' ' || *index =='\t') index++; for(i=0; i<strlen(index); i++) { if(*(index+i) == '\n') { *(index+i) = 0x00; break; } } toks = m_split(index, ";", PARSERULE_SIZE, &num_toks, 0); for(i=0; i<num_toks; i++) { char key[PARSERULE_SIZE]={0}; char value[PARSERULE_SIZE]={0}; char* idx; idx = toks[i]; while(*idx == ' ' || *idx == '\t') idx++; if(*idx == '\n' || *idx == 0x00) //是否是最后一个元素,即换行符 break; if(parse_key_value_pair(idx, key, value) < 0) { save_err_log("profile %s, line:%d, this line is not in the expected format", file_name, file_line); exit(1); } if(!strcmp(key, "classtype")) { strcpy(rule_node[0].type, value); } else if(!strcmp(key, "level")) { level = rule_level(value); if(level < 0) { m_split_free(&toks, num_toks); return -1; } rule_node[0].level = level; } else if(!strcmp(key, "msg")) { strcpy(rule_node[0].msg, value); } else if(!strcmp(key, "content") || !strcmp(key, "uricontent")) { if(parse_pattern(value, rule_node[rule_num].content, &rule_node[rule_num].content_len)<0) { save_err_log("profile %s, line:%d, this line is not in the expected format", file_name, file_line); m_split_free(&toks, num_toks); return -1; } rule_num++; } } for(i=0; i<rule_num; i++) { rule_node[i].nocase = NOCASE; rule_node[i].id = rule_id++; strcpy(rule_node[i].file_name, file_name); rule_node[i].file_line = file_line; if(i != 0) { strcpy(rule_node[i].type, rule_node[0].type); rule_node[i].level = rule_node[0].level; strcpy(rule_node[i].msg, rule_node[0].msg); } } m_split_free(&toks, num_toks); if(rule_node[0].content_len > 0 && rule_num >= 1) { rule_node_t* cur_rule_node = &rule_node[0]; if(rule_num == 1) { fpdetect_add_rule(cur_rule_node); } else { int j=1; for(j=1; j<rule_num; j++) { cur_rule_node = &rule_node[j]; if(cur_rule_node->content_len > 0) fpdetect_add_rule(cur_rule_node); } } } return 0; }