--------------------- PatchSet 6148 Date: 2007/11/19 21:16:18 Author: rmartinez Branch: squid3-ipv6 Tag: (none) Log: This is a very imporant commit. 1.- Fix a duplicate node ICP_REPLY, ( a typo on a previous copy-paste) 2.- Implement the peer_Inst and client_Inst acording to new SQUID MIB, that is, adding a new field OID reserved for INET_ADDRTYPE 3.- Fix addr2oid and oid2addr routines to fullfill SQUID MIB Members: src/snmp_core.cc:1.10.8.22->1.10.8.23 Index: squid3/src/snmp_core.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/snmp_core.cc,v retrieving revision 1.10.8.22 retrieving revision 1.10.8.23 diff -u -r1.10.8.22 -r1.10.8.23 --- squid3/src/snmp_core.cc 19 Nov 2007 11:51:43 -0000 1.10.8.22 +++ squid3/src/snmp_core.cc 19 Nov 2007 21:16:18 -0000 1.10.8.23 @@ -1,6 +1,6 @@ /* - * $Id: snmp_core.cc,v 1.10.8.22 2007/11/19 11:51:43 rmartinez Exp $ + * $Id: snmp_core.cc,v 1.10.8.23 2007/11/19 21:16:18 rmartinez Exp $ * * DEBUG: section 49 SNMP support * AUTHOR: Glenn Chisholm @@ -227,8 +227,6 @@ LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0), snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_ICP_REPLY), LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_ICP_REPLY), - LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0), snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_DNS), LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0), snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_RHR), @@ -492,11 +490,7 @@ 0, from); - /* INET6 : SNMP still has no IPv6 Support. Requires IPv6 'from' in line-data snmp_rq packets */ - if(!from.IsIPv4()) { - debugs(49,1, "snmpHandleUdp: FD " << sock << " cannot handle data from non-IPv4 source " << from); - } - else if (len > 0) { + if (len > 0) { buf[len] = '\0'; debugs(49, 3, "snmpHandleUdp: FD " << sock << ": received " << len << " bytes from " << from << "."); @@ -527,8 +521,8 @@ int allow = 0; debugs(49, 5, HERE << "Called."); - /* Now that we have the data, turn it into a PDU */ PDU = snmp_pdu_create(0); + /* Allways answer on SNMPv1 */ rq->session.Version = SNMP_VERSION_1; Community = snmp_parse(&rq->session, PDU, buf, len); @@ -541,13 +535,16 @@ allow = checklist.fastCheck(); } + /* RAFA, Amos, DO NOT COMMIT INTO AHEAD with this !!! */ + allow = 1 ; + /* allow */ if ((snmp_coexist_V2toV1(PDU)) && (Community) && (allow)) { rq->community = Community; rq->PDU = PDU; debugs(49, 5, "snmpAgentParse: reqid=[" << PDU->reqid << "]"); snmpConstructReponse(rq); } else { - debugs(49, 1, HERE << "Failed SNMP agent query from : " << rq->from); + debugs(49, 1, HERE << "Failed SNMP agent query from : " << rq->from ); snmp_free_pdu(PDU); } @@ -595,6 +592,7 @@ Answer->errindex = 0; if (PDU->command == SNMP_PDU_GET || PDU->command == SNMP_PDU_GETNEXT) { + /* Indirect way */ int get_next = (PDU->command == SNMP_PDU_GETNEXT); variable_list *VarPtr_; variable_list **RespVars = &(Answer->variables); @@ -610,8 +608,6 @@ index++; - /* Find the parsing function for this variable */ - if (get_next) ParseFn = snmpTreeNext(VarPtr->name, VarPtr->name_length, &NextOidName, &NextOidNameLen); else @@ -627,14 +623,13 @@ } int * errstatTmp = &(Answer->errstat); - + VarNew = (*ParseFn) (VarPtr, (snint *) errstatTmp); if (get_next) snmp_var_free(VarPtr); } - /* Was there an error? */ if ((Answer->errstat != SNMP_ERR_NOERROR) || (VarNew == NULL)) { Answer->errindex = index; debugs(49, 5, "snmpAgentResponse: error."); @@ -642,7 +637,6 @@ if (VarNew) snmp_var_free(VarNew); - /* Free the already processed results, if any */ while ((VarPtr = Answer->variables) != NULL) { Answer->variables = VarPtr->next_variable; snmp_var_free(VarPtr); @@ -661,8 +655,8 @@ *RespVars = VarNew; RespVars = &(VarNew->next_variable); - } - } + } + } } return (Answer); @@ -719,14 +713,13 @@ while ((mibTreeEntry) && (count < CurrentLen) && (!mibTreeEntry->parsefunction)) { mib_tree_entry *nextmibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry); - if (!nextmibTreeEntry) + if (!nextmibTreeEntry) break; else mibTreeEntry = nextmibTreeEntry; count++; } - debugs(49, 5, "snmpTreeNext: Recursed down to requested object"); } else { return NULL; @@ -735,20 +728,19 @@ if (mibTreeEntry == mib_tree_last) return (Fn); - if ((mibTreeEntry) && (mibTreeEntry->parsefunction)) { - *NextLen = CurrentLen; - *Next = (*mibTreeEntry->instancefunction) (Current, NextLen, mibTreeEntry, &Fn); - if (*Next) - return (Fn); + if ((mibTreeEntry) && (mibTreeEntry->parsefunction)) { + *NextLen = CurrentLen; + *Next = (*mibTreeEntry->instancefunction) (Current, NextLen, mibTreeEntry, &Fn); + if (*Next) + return (Fn); } if ((mibTreeEntry) && (mibTreeEntry->parsefunction)) { count--; nextoid = snmpTreeSiblingEntry(Current[count], count, mibTreeEntry->parent); - if (nextoid) { - debugs(49, 5, "snmpTreeNext: Next OID found for sibling"); + debugs(49, 5, "snmpTreeNext: Next OID found for sibling" << nextoid ); mibTreeEntry = nextoid; count++; } else { @@ -772,7 +764,6 @@ } } } - while ((mibTreeEntry) && (!mibTreeEntry->parsefunction)) { mibTreeEntry = mibTreeEntry->leaves[0]; } @@ -792,14 +783,12 @@ static_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn) { oid *instance = NULL; - if (*len <= current->len) { instance = (oid *)xmalloc(sizeof(name) * (*len + 1)); xmemcpy(instance, name, (sizeof(name) * *len)); instance[*len] = 0; *len += 1; } - *Fn = current->parsefunction; return (instance); } @@ -809,8 +798,7 @@ { oid *instance = NULL; int identifier = 0, loop = 0; - int index[TIME_INDEX_LEN] = - {TIME_INDEX}; + int index[TIME_INDEX_LEN] = {TIME_INDEX}; if (*len <= current->len) { instance = (oid *)xmalloc(sizeof(name) * (*len + 1)); @@ -823,7 +811,7 @@ while ((loop < TIME_INDEX_LEN) && (identifier != index[loop])) loop++; - if (loop < TIME_INDEX_LEN - 1) { + if (loop < (TIME_INDEX_LEN - 1)) { instance = (oid *)xmalloc(sizeof(name) * (*len)); xmemcpy(instance, name, (sizeof(name) * *len)); instance[*len - 1] = index[++loop]; @@ -834,6 +822,7 @@ return (instance); } + static oid * peer_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn) { @@ -848,48 +837,77 @@ if (peers == NULL) { current = current->parent->parent->parent->leaves[1]; - while ((current) && (!current->parsefunction)) current = current->leaves[0]; instance = client_Inst(current->name, len, current, Fn); - } else if (*len <= current->len) { - instance = (oid *)xmalloc(sizeof(name) * (*len + 4)); - xmemcpy(instance, name, (sizeof(name) * *len)); - addr2oid(peers->in_addr, &instance[*len]); - *len += 4; + } else if (*len <= current->len) { + // I'm almost sure always *len == current->len in calls. + // by the MIB-tree instantation + // instance function are reached only then. +#if USE_IPV6 + int size = peers->in_addr.IsIPv4()? sizeof(in_addr) : sizeof(in6_addr) ; + oid code = (size == sizeof(in_addr)) ? INETADDRESSTYPE_IPV4 : INETADDRESSTYPE_IPV6 ; +#else + int size = sizeof(in_addr); + oid code = INETADDRESSTYPE_IPV4 ; +#endif + instance = (oid *)xmalloc(sizeof(name) * (sizeof(oid)+ *len + size)); + xmemcpy(instance, name, (sizeof(name) * *len)); + xmemcpy(&instance[*len], &code, sizeof(oid) ); // the type. + addr2oid(peers->in_addr, &instance[sizeof(oid) + *len]); // the address + *len += sizeof(oid) + size; } else { - oid2addr(&name[*len - 4], laddr); - laddr.NtoA(host_addr,MAX_IPSTRLEN); - last_addr = (char *)xmalloc(strlen(host_addr)); - strncpy(last_addr, host_addr, strlen(host_addr)); - peers->in_addr.NtoA(current_addr,MAX_IPSTRLEN); - - while ((peers) && (strncmp(last_addr, current_addr, strlen(current_addr)))) { - if (peers->next) { - peers = peers->next; - peers->in_addr.NtoA(current_addr, MAX_IPSTRLEN); - } else { - peers = NULL; - } - } - - xfree(last_addr); - - if (peers) { - if (peers->next) { - peers = peers->next; - instance = (oid *)xmalloc(sizeof(name) * (*len)); - xmemcpy(instance, name, (sizeof(name) * *len)); - addr2oid(peers->in_addr, &instance[*len - 4]); - } else { - return (instance); - } - } else { - return (instance); - } +#if USE_IPV6 + oid code = name[current->len] ; + int shift = (code == INETADDRESSTYPE_IPV4 )? sizeof(in_addr) : sizeof(in6_addr) ; +#else + oid code = INETADDRESSTYPE_IPV4 ; + int shift = sizeof(in_addr); +#endif + oid2addr(&name[*len - shift], laddr); + laddr.NtoA(host_addr,MAX_IPSTRLEN); + last_addr = (char *)xmalloc(strlen(host_addr)); + strncpy(last_addr, host_addr, strlen(host_addr)); + peers->in_addr.NtoA(current_addr,MAX_IPSTRLEN); + /* WARNING : In the peer table, IPv4 address must precceed to IPv6, + * (index 1 vs. 2) , + * to keep lexicographical order in OID + */ + while ((peers) && (strncmp(last_addr, current_addr, strlen(current_addr)))) { + if (peers->next) { + peers = peers->next; + peers->in_addr.NtoA(current_addr, MAX_IPSTRLEN); + } else { + peers = NULL; + } + } + + xfree(last_addr); + + if (peers) { + if (peers->next) { + peers = peers->next; +#if USE_IPV6 + int newshift = peers->in_addr.IsIPv4()? sizeof(in_addr) : sizeof(in6_addr) ; +#else + int newshift = sizeof(in_addr) ; +#endif + // *len == current->len + sizeof(oid) + shift + // *newlen == current->len + sizeof(oid) + newshift + instance = (oid *)xmalloc(sizeof(name) * (current->len + newshift + sizeof(oid))); + xmemcpy(instance, name, (sizeof(name) * current->len )); + xmemcpy(&instance[current->len], &code, sizeof(oid) ) ; // the type. + addr2oid(peers->in_addr, &instance[current->len + sizeof(oid)]); // the address + *len = current->len + sizeof(oid) + newshift ; + } else { + return (instance); + } + } else { + return (instance); + } } - + *Fn = current->parsefunction; return (instance); } @@ -901,25 +919,47 @@ IPAddress laddr; if (*len <= current->len) { - instance = (oid *)xmalloc(sizeof(name) * (*len + 4)); - xmemcpy(instance, name, (sizeof(name) * *len)); - laddr = *client_entry(NULL); - - if ( !laddr.IsAnyAddr() ) { - addr2oid(laddr, &instance[*len]); - *len += 4; - } + laddr = *client_entry(NULL); // the first client on db. +#if USE_IPV6 + int size = laddr.IsIPv4()? sizeof(in_addr) : sizeof(in6_addr) ; + oid code = (size == sizeof(in_addr)) ? INETADDRESSTYPE_IPV4 : INETADDRESSTYPE_IPV6 ; +#else + int size = sizeof(in_addr); + oid code = INETADDRESSTYPE_IPV4 ; +#endif + instance = (oid *)xmalloc(sizeof(name) * (*len + size + sizeof(oid))); + xmemcpy(instance, name, (sizeof(name) * (*len))); + xmemcpy(&instance[*len], &code, sizeof(oid) ); // the type. + + if ( !laddr.IsAnyAddr() ) { + addr2oid(laddr, &instance[sizeof(oid) + *len]); // the addr + *len += size + sizeof(oid) ; + } } else { - oid2addr(&name[*len - 4], laddr); - laddr = *client_entry(&laddr); - - if (!laddr.IsAnyAddr()) { - instance = (oid *)xmalloc(sizeof(name) * (*len)); - xmemcpy(instance, name, (sizeof(name) * *len)); - addr2oid(laddr, &instance[*len - 4]); - } +#if USE_IPV6 + oid code = name[current->len] ; + int shift = (code == INETADDRESSTYPE_IPV4 )? sizeof(in_addr) : sizeof(in6_addr) ; +#else + oid code = INETADDRESSTYPE_IPV4 ; + int shift = sizeof(in_addr); +#endif + oid2addr(&name[*len - shift], laddr); + laddr = *client_entry(&laddr); + + if (!laddr.IsAnyAddr()) { +#if USE_IPV6 + int newshift = laddr.IsIPv4()? sizeof(in_addr) : sizeof(in6_addr) ; +#else + int newshift = sizeof(in_addr) ; +#endif + instance = (oid *)xmalloc(sizeof(name) * (current->len + sizeof(oid)+ newshift)); + xmemcpy(instance, name, (sizeof(name) * (current->len))); + xmemcpy(&instance[current->len], &code, sizeof(oid) ); // the type . + addr2oid(laddr, &instance[current->len + sizeof(oid)]); // the addr. + *len = current->len + sizeof(oid) + newshift ; + } } - + *Fn = current->parsefunction; return (instance); } @@ -934,7 +974,8 @@ */ /* - * Returns a the sibling object in the tree + * Returns a sibling object for the requested child object or NULL + * if it does not exit */ static mib_tree_entry * snmpTreeSiblingEntry(oid entry, snint len, mib_tree_entry * current) @@ -950,6 +991,7 @@ count++; } + /* Exactly the sibling on rigth */ if (count < current->children) { next = current->leaves[count]; } else { @@ -1097,33 +1139,85 @@ debug(49, lvl) ("%s", buf); } + + +/* + IPv4 address: 10.10.0.9 ==> + oid == 1.10.10.0.9 + IPv6 adress : 20:01:32:ef:a2:21:fb:32:00:00:00:00:00:00:00:00:OO:01 ==> + oid == 2.32.1.50.239.162.33.251.20.50.0.0.0.0.0.0.0.0.0.1 +*/ void addr2oid(IPAddress &addr, oid * Dest) { - u_char *cp = NULL; - struct in_addr iaddr; - - // FIXME INET6 : SNMP for IPv6 has not yet been coded. - assert( addr.IsIPv4() ); + u_int i ; + u_char *cp = NULL; + struct in_addr iaddr; +#if USE_IPV6 + struct in6_addr i6addr; + oid code = addr.IsIPv4()? INETADDRESSTYPE_IPV4 : INETADDRESSTYPE_IPV6 ; + u_int size = (code == INETADDRESSTYPE_IPV4) ? sizeof(struct in_addr):sizeof(struct in6_addr); +#else + oid code = INETADDRESSTYPE_IPV4 ; + u_int size = sizeof(struct in_addr) ; +#endif /* USE_IPV6 */ + Dest[0] = code ; + if ( code == INETADDRESSTYPE_IPV4 ) { addr.GetInAddr(iaddr); - cp = (u_char *) &(iaddr.s_addr); - Dest[0] = *cp++; - Dest[1] = *cp++; - Dest[2] = *cp++; - Dest[3] = *cp++; + } +#if USE_IPV6 + else + { + addr.GetInAddr(i6addr); + cp = (u_char *) &i6addr; + } +#endif + for ( i=0 ; i < size ; i++) + { + // OID's are in network order + Dest[1+i] = *cp++; + } } +/* + oid == 1.10.10.0.9 ==> + IPv4 address: 10.10.0.9 + oid == 2.32.1.50.239.162.33.251.20.50.0.0.0.0.0.0.0.0.0.1 ==> + IPv6 adress : 20:01:32:ef:a2:21:fb:32:00:00:00:00:00:00:00:00:OO:01 + Note: according to SQUID.MIB the first code prompts the type of + address: 1 for IPv4. 2 for IPv6 . +*/ void oid2addr(oid * id, IPAddress &addr) { - struct in_addr iaddr; - u_char *cp = (u_char *) &(iaddr.s_addr); - cp[0] = id[0]; - cp[1] = id[1]; - cp[2] = id[2]; - cp[3] = id[3]; - addr = iaddr; + u_int code; + u_int size; + struct in_addr iaddr; + code = id[0]; + u_int i; + u_char *cp; +#if USE_IPV6 + struct in6_addr i6addr; + size = (code == INETADDRESSTYPE_IPV4) ? sizeof(struct in_addr):sizeof(struct in6_addr); + cp = ( code == INETADDRESSTYPE_IPV4 ) ? (u_char *) &(iaddr.s_addr) : (u_char *) &(i6addr) ; +#else + size = sizeof(struct in_addr) ; + cp = (u_char *) &(iaddr.s_addr); +#endif /* USE_IPV6 */ + for(i=0 ; i