Annotation of 43BSDReno/contrib/isode-beta/snmp/gawk-2.11/snmp.c, revision 1.1.1.1

1.1       root        1: /* snmp.c - SNMP changes for gawk */
                      2: 
                      3: #ifndef        lint
                      4: static char *rcsid = "$Header: /f/osi/snmp/gawk-2.11/RCS/snmp.c,v 7.2 90/06/06 22:59:38 mrose Exp $";
                      5: #endif
                      6: 
                      7: /* 
                      8:  * $Header: /f/osi/snmp/gawk-2.11/RCS/snmp.c,v 7.2 90/06/06 22:59:38 mrose Exp $
                      9:  *
                     10:  *
                     11:  * $Log:       snmp.c,v $
                     12:  * Revision 7.2  90/06/06  22:59:38  mrose
                     13:  * update
                     14:  * 
                     15:  * Revision 7.1  90/03/22  16:44:22  mrose
                     16:  * touch-up
                     17:  * 
                     18:  * Revision 7.0  90/03/05  10:33:19  mrose
                     19:  * *** empty log message ***
                     20:  * 
                     21:  */
                     22: 
                     23: /*
                     24:  *                               NOTICE
                     25:  *
                     26:  *    Acquisition, use, and distribution of this module and related
                     27:  *    materials are subject to the restrictions of a license agreement.
                     28:  *    Consult the Preface in the User's Manual for the full terms of
                     29:  *    this agreement.
                     30:  *
                     31:  */
                     32: 
                     33: 
                     34: #ifdef SNMP
                     35: #include "awk.h"
                     36: #ifdef HUGE
                     37: #undef HUGE
                     38: #endif
                     39: #include <isode/snmp/objects.h>
                     40: #include <isode/pepy/SNMP-types.h>
                     41: #include <isode/dgram.h>
                     42: #include <isode/internet.h>
                     43: #include <isode/tailor.h>
                     44: 
                     45: /*    DATA */
                     46: 
                     47: int    debug = 0;
                     48: 
                     49: int    snmp_enabled = 1;
                     50: int    snmp_scalars_as_arrays = 1;
                     51: char   *snmp_file = NULLCP;
                     52: 
                     53: static int     snmp_id = 0;
                     54: static int     snmp_retries = 3;
                     55: static int     snmp_timeout = 10;
                     56: 
                     57: static char   *snmp_agent = NULL;
                     58: static char   *snmp_community = NULL;
                     59: 
                     60: NODE   *AGENT_node,
                     61:        *COMMUNITY_node,
                     62:        *DIAGNOSTIC_node,
                     63:        *ERROR_node,
                     64:        *RETRIES_node,
                     65:        *TIMEOUT_node;
                     66: NODE   *Ndot_string;
                     67: 
                     68: static int     snmp_fd = NOTOK;
                     69: static struct sockaddr_in in_socket;
                     70: static PS      ps = NULLPS;
                     71: 
                     72: static struct type_SNMP_Message        msgs;
                     73: static struct type_SNMP_PDUs           pdus;
                     74: static struct type_SNMP_PDU            parms;
                     75: static struct type_SNMP_VarBindList    vps;
                     76: static struct type_SNMP_VarBind        vs;
                     77: 
                     78: 
                     79: struct snmp_search {
                     80:     struct search s_search;    /* must be first entry */
                     81: 
                     82:     OT     s_parent;
                     83: 
                     84:     PE     s_pe;
                     85:     struct type_SNMP_VarBindList *s_bindings;
                     86: 
                     87:     struct snmp_search *s_prev;
                     88:     struct snmp_search *s_next;
                     89: };
                     90: 
                     91: static struct snmp_search *head = NULL;
                     92: static struct snmp_search *tail = NULL;
                     93: 
                     94: 
                     95: char   *snmp_error (), *snmp_variable ();
                     96: 
                     97: 
                     98: #ifndef        SYS5
                     99: long   random ();
                    100: #endif
                    101: 
                    102: /*    INIT */
                    103: 
                    104: int    check_snmp (r, name)
                    105: NODE   *r;
                    106: char   *name;
                    107: {
                    108:     char    c;
                    109:     register char   *cp;
                    110:     OT     ot;
                    111:     static int inited = 0;
                    112: 
                    113:     if (inited == 0) {
                    114:        inited = 1;
                    115: 
                    116:        snmp_onceonly ();
                    117:     }
                    118: 
                    119:     for (cp = name; is_identchar (*cp); cp++)
                    120:        continue;
                    121:     if (c = *cp)
                    122:        *cp = NULL;
                    123:     if ((ot = text2obj (name)) && ot -> ot_syntax) {
                    124:        r -> magic = (caddr_t) ot;
                    125:        if (ot -> ot_getfnx || snmp_scalars_as_arrays)
                    126:            r -> type = Node_var_array;
                    127:     }
                    128:     *cp = c;
                    129: }
                    130: 
                    131: /*  */
                    132: 
                    133: int    f_integer (), f_octets (), f_display (), f_objectID (), f_null (),
                    134:        f_ipaddr (), f_clnpaddr ();
                    135: 
                    136: 
                    137: static struct pair {
                    138:     char   *pp_name;
                    139:     IFP            pp_value;
                    140: }      pairs[] = {
                    141:     "INTEGER", f_integer,
                    142:     "Services", f_integer,
                    143:     "OctetString", f_octets,
                    144:     "DisplayString", f_display,
                    145:     "ObjectID", f_objectID,
                    146:     "NULL", f_null,
                    147:     "IpAddress", f_ipaddr,
                    148:     "NetworkAddress", f_ipaddr,
                    149:     "Counter", f_integer,
                    150:     "Gauge", f_integer,
                    151:     "TimeTicks", f_integer,
                    152:     "ClnpAddress", f_clnpaddr,
                    153: 
                    154:     NULL
                    155: };
                    156: 
                    157: 
                    158: static snmp_onceonly () {
                    159:     int            i;
                    160:     register struct pair *pp;
                    161:     register struct type_SNMP_Message *msg = &msgs;
                    162:     register struct type_SNMP_PDUs *pdu = &pdus;
                    163:     register struct type_SNMP_PDU *parm = &parms;
                    164:     register struct type_SNMP_VarBindList *vp = &vps;
                    165:     register struct type_SNMP_VarBind *v = &vs;
                    166:     OS     os;
                    167:     register OT            ot,
                    168:                    ot2;
                    169: 
                    170:     Ndot_string = make_string (".", 1);
                    171:     Ndot_string -> flags |= PERM;
                    172: 
                    173:     if (readobjects (snmp_file) == NOTOK)
                    174:        fatal ("readobjects: %s", PY_pepy);
                    175: 
                    176:                                /* mark entries that are actually arrays! */
                    177:     for (ot = text2obj ("iso"); ot; ot = ot -> ot_next) {
                    178:        if (ot -> ot_syntax
                    179:                || (i = strlen (ot -> ot_text)) <= 5
                    180:                || strcmp (ot -> ot_text + i - 5, "Entry"))
                    181:            continue;
                    182:        for (ot2 = ot -> ot_children; ot2; ot2 = ot2 -> ot_sibling)
                    183:            if (ot2 -> ot_children || !ot2 -> ot_syntax)
                    184:                break;
                    185:        if (ot2)
                    186:            continue;
                    187:        for (ot2 = ot -> ot_children; ot2; ot2 = ot2 -> ot_sibling)
                    188:            ot2 -> ot_getfnx = (IFP) 1;
                    189:     }
                    190: 
                    191:     for (pp = pairs; pp -> pp_name; pp++)
                    192:        if ((os = text2syn (pp -> pp_name)) == NULL)
                    193:            fatal ("lost syntax for \"%s\"", pp -> pp_name);
                    194:         else
                    195:            os -> os_decode = pp -> pp_value;
                    196: 
                    197:     bzero ((char *) msg, sizeof *msg);
                    198:     msg -> version = int_SNMP_version_version__1;
                    199:     msg -> data = pdu;
                    200: 
                    201:     bzero ((char *) pdu, sizeof *pdu);
                    202:     pdu -> offset = type_SNMP_PDUs_get__request;
                    203:     pdu -> un.get__request = parm;
                    204: 
                    205:     bzero ((char *) parm, sizeof *parm);
                    206:     parm -> variable__bindings = vp;
                    207: 
                    208:     bzero ((char *) vp, sizeof *vp);
                    209:     vp -> VarBind = v;
                    210: 
                    211:     bzero ((char *) v, sizeof *v);
                    212:     if ((v -> value = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, PE_PRIM_NULL))
                    213:            == NULLPE)
                    214:        fatal ("pe_alloc: out of memory");
                    215: 
                    216:     ps_len_strategy = PS_LEN_LONG;
                    217: 
                    218: #ifndef        SYS5
                    219:     srandom (getpid ());
                    220: #else
                    221:     srand (getpid ());
                    222: #endif
                    223: }
                    224: 
                    225: /*    GET */
                    226: 
                    227: int    snmp_get (ptr, instname)
                    228: NODE   *ptr;
                    229: char   *instname;
                    230: {
                    231:     int            gotone,
                    232:            retries,
                    233:            status = -1;
                    234:     struct type_SNMP_Message *msg = &msgs;
                    235:     register struct type_SNMP_PDU *parm = msg -> data -> un.get__request;
                    236:     register struct type_SNMP_VarBind *v =
                    237:                                        parm -> variable__bindings -> VarBind;
                    238:     PE     pe = NULLPE,
                    239:            p = NULLPE;
                    240:     OID            oid;
                    241:     OT     ot = (OT) ptr -> magic;
                    242:     NODE   *value = NULL;
                    243: 
                    244:     if (snmp_ready () == NOTOK)
                    245:        goto out;
                    246: 
                    247:     parm -> request__id = snmp_id;
                    248:     if (v -> name)
                    249:        free_SNMP_ObjectName (v -> name), v -> name = NULL;
                    250: 
                    251:     if (instname == NULL) {
                    252:        if (ot -> ot_getfnx || snmp_scalars_as_arrays) {
                    253:            register struct snmp_search *s;
                    254: 
                    255:            for (s = tail; s; s = s -> s_prev) {
                    256:                register struct type_SNMP_VarBindList *vp;
                    257: 
                    258:                if (ot -> ot_name -> oid_nelem
                    259:                           != (oid = s -> s_parent -> ot_name) -> oid_nelem + 1
                    260:                        || bcmp ((char *) ot -> ot_name -> oid_elements,
                    261:                                 (char *) oid -> oid_elements,
                    262:                                 oid -> oid_nelem
                    263:                                         * sizeof ot -> ot_name -> oid_elements[0]))
                    264:                    continue;
                    265:                for (vp = s -> s_bindings; vp; vp = vp -> next) {
                    266:                    v = vp -> VarBind;
                    267: 
                    268:                    if (ot -> ot_name -> oid_nelem >= v -> name -> oid_nelem)
                    269:                        fatal ("snmp_get: internal error");
                    270:                    if (bcmp ((char *) v -> name -> oid_elements,
                    271:                              (char *) ot -> ot_name -> oid_elements,
                    272:                              ot -> ot_name -> oid_nelem
                    273:                                  * sizeof ot -> ot_name -> oid_elements[0]))
                    274:                        continue;
                    275: 
                    276:                    goto get_value;
                    277:                }
                    278:                status = int_SNMP_error__status_noSuchName;
                    279:                goto out;
                    280:            }
                    281:            if (ot -> ot_getfnx) {
                    282:                snmp_diag (NULLCP,
                    283:                           "can't use SNMP array variable as scalar unless within for-in construct");
                    284:                goto out;
                    285:            }
                    286:        }
                    287: 
                    288:        if ((oid = v -> name = oid_extend (ot -> ot_name, 1)) == NULL) {
                    289: no_mem_for_inst: ;
                    290:            snmp_diag (NULLCP, "oid_extend: out of memory");
                    291:            goto out;
                    292:        }
                    293:        v -> name -> oid_elements[v -> name -> oid_nelem - 1] = 0;
                    294:     }
                    295:     else {
                    296:        register int    i;
                    297:        register unsigned int *ip,
                    298:                              *jp;
                    299:        OID     inst = str2oid (instname);
                    300: 
                    301:        if (inst == NULL) {
                    302:            snmp_diag (NULLCP, "str2oid: bad instance identifier \"%s\"",
                    303:                       instname);
                    304:            goto out;
                    305:        }
                    306:        if ((oid = v -> name = oid_extend (ot -> ot_name, inst -> oid_nelem))
                    307:                == NULL)
                    308:            goto no_mem_for_inst;
                    309:        ip = oid -> oid_elements + oid -> oid_nelem - inst -> oid_nelem;
                    310:        jp = inst -> oid_elements;
                    311:        for (i = inst -> oid_nelem; i > 0; i--)
                    312:            *ip++ = *jp++;
                    313:     }
                    314: 
                    315:     if (encode_SNMP_Message (&pe, 1, 0, NULLCP, msg) == NOTOK) {
                    316:        snmp_diag (NULLCP, "encode_SNMP_Message: %s", PY_pepy);
                    317:        goto out;
                    318:     }
                    319: 
                    320:     msg = NULL, gotone = 0;
                    321:     for (retries = snmp_retries; retries > 0; ) {
                    322:        int     len;
                    323:        fd_set  rfds;
                    324: 
                    325:        if (debug > 1)
                    326:            print_SNMP_Message (pe, 1, NULLIP, NULLVP, NULLCP);
                    327:        len = ps -> ps_byteno;
                    328:        if (pe2ps (ps, pe) == NOTOK) {
                    329:            snmp_diag (NULLCP, "pe2ps: %s", ps_error (ps -> ps_errno));
                    330:            goto error_x;
                    331:        }
                    332:        if (debug > 0 && (len = ps -> ps_byteno - len) > 484)
                    333:            fprintf (stderr, "sent message of %d octets\n", len);
                    334: 
                    335:        FD_ZERO (&rfds);
                    336:        FD_SET (snmp_fd, &rfds);
                    337: 
                    338:        switch (xselect (snmp_fd + 1, &rfds, NULLFD, NULLFD, snmp_timeout)) {
                    339:            case NOTOK:
                    340:                snmp_diag ("failed", "xselect");
                    341:                goto error_x;
                    342: 
                    343:            default:
                    344:                if (FD_ISSET (snmp_fd, &rfds))
                    345:                    break;
                    346:                /* else fall... */
                    347:            case OK:
                    348:                if (debug > 0)
                    349:                    fprintf (stderr, "timeout...\n");
                    350:                retries--;
                    351:                continue;
                    352:        }
                    353: 
                    354:        if ((p = ps2pe (ps)) == NULLPE) {
                    355:            snmp_diag (NULLCP, "ps2pe: %s", ps_error (ps -> ps_errno));
                    356:            goto error_x;
                    357:        }
                    358:        if (decode_SNMP_Message (p, 1, NULLIP, NULLVP, &msg) == NOTOK) {
                    359:            snmp_diag (NULLCP, "decode_SNMP_Message: %s", PY_pepy);
                    360:            goto out;
                    361:        }
                    362:        if (debug > 1)
                    363:            print_SNMP_Message (p, 1, NULLIP, NULLVP, NULLCP);
                    364: 
                    365:        if (msg -> data -> offset != type_SNMP_PDUs_get__response) {
                    366:            snmp_diag (NULLCP, "unexpected message type %d",
                    367:                       msg -> data -> offset);
                    368:            goto out;
                    369:        }
                    370: 
                    371:        if ((parm = msg -> data -> un.get__response) -> request__id == snmp_id)
                    372:            break;
                    373: 
                    374:        if (debug > 0)
                    375:            fprintf (stderr, "bad ID (got %d, wanted %d)\n",
                    376:                     parm -> request__id, snmp_id);
                    377: 
                    378:        if (msg)
                    379:            free_SNMP_Message (msg), msg = NULL;
                    380:        if (p)
                    381:            pe_free (p), p = NULLPE;
                    382: 
                    383:        gotone++;
                    384:     }
                    385:     if (retries <= 0) {
                    386:        snmp_diag (NULLCP,
                    387:                   "no %sresponse within %d retries of %s%d second%s each",
                    388:                   gotone ? "acceptable " : "", snmp_retries + gotone,
                    389:                   gotone ? "upto " : "",
                    390:                   snmp_timeout, snmp_timeout != 1 ? "s" : "");
                    391:        goto out;
                    392:     }
                    393: 
                    394:     if ((status = parm -> error__status) != int_SNMP_error__status_noError) {
                    395:        char   *cp = snmp_variable (parm, parm -> error__index);
                    396: 
                    397:        snmp_diag (NULLCP, cp ? "%s at position %d (%s)" : "%s at position %d",
                    398:                   snmp_error (status), parm -> error__index, cp);
                    399:        goto out;
                    400:     }
                    401: 
                    402:     if (parm -> variable__bindings == NULL
                    403:            || (v = parm -> variable__bindings -> VarBind) == NULL) {
                    404:        snmp_diag (NULLCP, "missing variable in response");
                    405:        goto out;
                    406:     }
                    407:     if (debug > 0 && parm -> variable__bindings -> next)
                    408:        fprintf (stderr, "too many responses: %s\n",
                    409:                 oid2ode (parm -> variable__bindings -> next -> VarBind -> name));
                    410: 
                    411:     if (oid_cmp (oid, v -> name)) {
                    412:        char    buffer[BUFSIZ];
                    413: 
                    414:        (void) strcpy (buffer, oid2ode (v -> name));
                    415:        snmp_diag (NULLCP, "wrong variable returned (got %s, wanted %s)",
                    416:                 buffer, oid2ode (oid));
                    417:        goto out;
                    418:     }
                    419:                 
                    420: get_value: ;
                    421:     if ((*ot -> ot_syntax -> os_decode) (&value, v -> value) == NOTOK) {
                    422:        snmp_diag (NULLCP, "decode error for variable \"%s\": %s",
                    423:                 oid2ode (v -> name), PY_pepy);
                    424:        goto out;
                    425:     }
                    426: 
                    427:     goto out;
                    428: 
                    429: error_x: ;
                    430:     if (ps)
                    431:        ps_free (ps), ps = NULLPS;
                    432:     if (snmp_fd != NOTOK)
                    433:        (void) close_udp_socket (snmp_fd), snmp_fd = NOTOK;
                    434: 
                    435: out: ;
                    436:     if (msg && msg != &msgs)
                    437:        free_SNMP_Message (msg);
                    438:     if (p)
                    439:        pe_free (p);
                    440:     if (pe)
                    441:        pe_free (pe);
                    442: 
                    443:     deref = ptr -> var_value;
                    444:     do_deref ();
                    445: 
                    446:     ptr -> var_value = value ? value : Nnull_string;
                    447: 
                    448:     assign_number (&ERROR_node -> var_value, (AWKNUM) status);
                    449: }
                    450: 
                    451: /*  */
                    452: 
                    453: static snmp_ready () {
                    454:     int            changed = 0;
                    455:     char   *pp;
                    456:     struct sockaddr_in lo_socket;
                    457:     register struct sockaddr_in *lsock = &lo_socket;
                    458:     register struct sockaddr_in *isock = &in_socket;
                    459:     register struct hostent *hp;
                    460:     register struct servent *sp;
                    461:     register NODE   *tmp;
                    462: 
                    463:     deref = DIAGNOSTIC_node -> var_value;
                    464:     do_deref ();
                    465: 
                    466:     DIAGNOSTIC_node -> var_value = Nnull_string;
                    467: 
                    468:     if ((snmp_retries = (int) RETRIES_node -> var_value -> numbr) <= 0)
                    469:        snmp_retries = 1;
                    470:     if ((snmp_timeout = (int) TIMEOUT_node -> var_value -> numbr) <= 0)
                    471:        snmp_timeout = 1;
                    472: 
                    473:    if (snmp_id >= 0x7fffffff)
                    474:        snmp_id = 0;
                    475:     snmp_id++;
                    476: 
                    477:     if (snmp_fd == NOTOK || ps == NULLPS)
                    478:        changed++;
                    479: 
                    480:     tmp = force_string (AGENT_node -> var_value);
                    481:     if (snmp_agent == NULL || strcmp (snmp_agent, tmp -> stptr)) {
                    482:        if (snmp_agent)
                    483:            free (snmp_agent), snmp_agent = NULL;
                    484: 
                    485:        emalloc (snmp_agent, char *, strlen (tmp -> stptr) + 1, "snmp_init1");
                    486:        (void) strcpy (snmp_agent, tmp -> stptr);
                    487: 
                    488:        changed++;
                    489:     }
                    490: 
                    491:     tmp = force_string (COMMUNITY_node -> var_value);
                    492:     if (snmp_community == NULL || strcmp (snmp_community, tmp -> stptr)) {
                    493:        register struct type_SNMP_Message *msg = &msgs;
                    494: 
                    495:        if (snmp_community)
                    496:            free (snmp_community), snmp_community = NULL;
                    497: 
                    498:        emalloc (snmp_community, char *, strlen (tmp -> stptr) + 1,
                    499:                 "snmp_init2");
                    500:        (void) strcpy (snmp_community, tmp -> stptr);
                    501: 
                    502:        if ((msg -> community = str2qb (snmp_community,
                    503:                                        strlen (snmp_community), 1)) == NULL) {
                    504:            snmp_diag (NULLCP, "str2qb: out of memory");
                    505:            free (snmp_community), snmp_community = NULL;
                    506:            return NOTOK;
                    507:        }
                    508:     }
                    509: 
                    510:     if (changed) {
                    511:        if (ps)
                    512:            ps_free (ps), ps = NULLPS;
                    513:        if (snmp_fd != NOTOK)
                    514:            (void) close_udp_socket (snmp_fd), snmp_fd = NOTOK;
                    515:     }
                    516:     else
                    517:        return OK;
                    518: 
                    519:     bzero ((char *) lsock, sizeof *lsock);
                    520:     if ((hp = gethostbystring (pp = strcmp (snmp_agent, "localhost")
                    521:                                        ? getlocalhost () : "localhost"))
                    522:            == NULL) {
                    523:        snmp_diag (NULLCP, "%s: unknown host", pp);
                    524:        return NOTOK;
                    525:     }
                    526:     lsock -> sin_family = hp -> h_addrtype;
                    527:     inaddr_copy (hp, lsock);
                    528:     if ((snmp_fd = start_udp_client (lsock, 0, 0, 0)) == NOTOK) {
                    529:        snmp_diag ("failed", "start_udp_server");
                    530:        return NOTOK;
                    531:     }
                    532: 
                    533:     bzero ((char *) isock, sizeof *isock);
                    534:     if ((hp = gethostbystring (snmp_agent)) == NULL) {
                    535:        snmp_diag (NULLCP, "%s: unknown host", snmp_agent);
                    536:        return NOTOK;
                    537:     }
                    538:     isock -> sin_family = hp -> h_addrtype;
                    539:     isock -> sin_port = (sp = getservbyname ("snmp", "udp"))
                    540:                                        ? sp -> s_port
                    541:                                        : htons ((u_short) 161);
                    542:     inaddr_copy (hp, isock);
                    543: 
                    544:     if (join_udp_server (snmp_fd, isock) == NOTOK) {
                    545:        snmp_diag ("failed", "join_udp_server");
                    546:        return NOTOK;
                    547:     }
                    548: 
                    549:     if ((ps = ps_alloc (dg_open)) == NULLPS
                    550:            || dg_setup (ps, snmp_fd, MAXDGRAM, read_udp_socket,
                    551:                         write_udp_socket) == NOTOK) {
                    552:        if (ps == NULLPS)
                    553:            snmp_diag (NULLCP, "ps_alloc: out of memory");
                    554:        else
                    555:            snmp_diag (NULLCP, "dg_setup: %s", ps_error (ps -> ps_errno));
                    556: 
                    557:        return NOTOK;
                    558:     }
                    559: 
                    560: #ifndef        SYS5
                    561:     snmp_id = ((int) random ()) & 0x7fffffff;
                    562: #else
                    563:     snmp_id = ((int) rand ()) & 0x7fffffff;
                    564: #endif
                    565: 
                    566:     return OK;
                    567: }
                    568: 
                    569: /*  */
                    570: 
                    571: #ifndef        lint
                    572: static snmp_diag (va_alist)
                    573: va_dcl
                    574: {
                    575:     char   *what,
                    576:            buffer[BUFSIZ];
                    577:     va_list ap;
                    578: 
                    579:     va_start (ap);
                    580: 
                    581:     what = va_arg (ap, char *);
                    582: 
                    583:     _asprintf (buffer, what, ap);
                    584: 
                    585:     va_end (ap);
                    586: 
                    587:     if (debug > 0)
                    588:        fprintf (stderr, "%s\n", buffer);
                    589: 
                    590:     deref = DIAGNOSTIC_node -> var_value;
                    591:     do_deref ();
                    592: 
                    593:     DIAGNOSTIC_node -> var_value = make_string (buffer, strlen (buffer));
                    594: }
                    595: #else
                    596: /* VARARGS */
                    597: 
                    598: static snmp_diag (what, fmt)
                    599: char   *what,
                    600:        *fmt;
                    601: {
                    602:     snmp_diag (what, fmt);
                    603: }
                    604: #endif
                    605: 
                    606: /*    SCAN */
                    607: 
                    608: struct search *snmp_assoc_scan (symbol)
                    609: NODE   *symbol;
                    610: {
                    611:     register struct snmp_search *s;
                    612:     register OT            ot = (OT) symbol -> magic;
                    613:     register struct type_SNMP_VarBindList **vp;
                    614: 
                    615:     if (!ot -> ot_getfnx && !snmp_scalars_as_arrays)
                    616:        fatal ("can't use SNMP scalar variable as control for for-in");
                    617: 
                    618:     emalloc (s, struct snmp_search *, sizeof *s, "snmp_assoc_scan1");
                    619:     bzero ((char *) s, sizeof *s);
                    620: 
                    621:     ot -> ot_name -> oid_nelem--;
                    622:     s -> s_parent = name2obj (ot -> ot_name);
                    623:     ot -> ot_name -> oid_nelem++;
                    624: 
                    625:     if ((ot = s -> s_parent) == NULL)
                    626:        fatal ("unable to find parent for \"%s\"", snmp_name (symbol));
                    627: 
                    628:     vp = &s -> s_bindings;
                    629:     for (ot = ot -> ot_children; ot; ot = ot -> ot_sibling) {
                    630:        register struct type_SNMP_VarBindList *bind;
                    631:        register struct type_SNMP_VarBind *v;
                    632: 
                    633:        if (!ot -> ot_syntax)
                    634:            continue;
                    635:        emalloc (bind, struct type_SNMP_VarBindList *, sizeof *bind,
                    636:                 "snmp_assoc_scan2");
                    637:        *vp = bind, vp = &bind -> next;
                    638:        bind -> next = NULL;
                    639: 
                    640:        emalloc (v, struct type_SNMP_VarBind *, sizeof *v, "snmp_assoc_scan3");
                    641:        bind -> VarBind = v;
                    642:        if ((v -> name = oid_cpy (ot -> ot_name)) == NULL)
                    643:            fatal ("oid_cpy: out of memory");
                    644:        if ((v -> value = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, PE_PRIM_NULL))
                    645:                == NULLPE)
                    646:            fatal ("pe_alloc: out of memory");
                    647:     }
                    648: 
                    649:     if (head == NULL)
                    650:        head = tail = s;
                    651:     else {
                    652:        tail -> s_next = s;
                    653:        s -> s_prev = tail;
                    654:        tail = s;
                    655:     }
                    656: 
                    657:     return snmp_assoc_next (&s -> s_search, 0);
                    658: }
                    659: 
                    660: /*  */
                    661: 
                    662: struct search *snmp_assoc_next (lookat, done)
                    663: struct search *lookat;
                    664: int    done;
                    665: {
                    666:     int            i;
                    667:     char   *cp;
                    668:     register struct snmp_search *s = (struct snmp_search *) lookat;
                    669:     register struct search *l = &s -> s_search;
                    670:     struct OIDentifier oids;
                    671:     OID            oid;
                    672:     OT     ot = s -> s_parent;
                    673:     register struct type_SNMP_VarBind *v;
                    674: 
                    675:     deref = l -> retval, l -> retval = NULL;
                    676:     do_deref ();
                    677: 
                    678:     if (done || snmp_get_next (s) == NOTOK || s -> s_bindings == NULL) {
                    679:        if (s -> s_bindings)
                    680:            free_SNMP_VarBind (s -> s_bindings);
                    681:        if (s -> s_pe)
                    682:            pe_free (s -> s_pe);
                    683:        if (tail != s)
                    684:            fatal ("snmp_assoc_next: internal error1");
                    685:        if (tail = s -> s_prev)
                    686:            tail -> s_next = NULL;
                    687:        else
                    688:            head = NULL;
                    689: 
                    690:        free ((char *) s);
                    691:        return NULL;
                    692:     }
                    693: 
                    694:     if ((v = s -> s_bindings -> VarBind) == NULL || (oid = v -> name) == NULL)
                    695:        fatal ("snmp_assoc_next: internal error2");
                    696:     if (ot -> ot_name -> oid_nelem >= oid -> oid_nelem
                    697:            || bcmp ((char *) ot -> ot_name -> oid_elements,
                    698:                     (char *) oid -> oid_elements,
                    699:                     ot -> ot_name -> oid_nelem
                    700:                             * sizeof oid -> oid_elements[0]))
                    701:        fatal ("snmp_assoc_next: internal error3");
                    702: 
                    703:     oids.oid_nelem = oid -> oid_nelem - (i = ot -> ot_name -> oid_nelem + 1);
                    704:     oids.oid_elements = oid -> oid_elements + i;
                    705: 
                    706:     cp = sprintoid (&oids);
                    707: 
                    708:     l -> retval = make_string (cp, strlen (cp));
                    709: 
                    710:     return l;
                    711: }
                    712: 
                    713: /*  */
                    714: 
                    715: static int  snmp_get_next (s)
                    716: register struct snmp_search *s;
                    717: {
                    718:     int            gotone,
                    719:            result = NOTOK,
                    720:            retries,
                    721:            status = -1;
                    722:     struct type_SNMP_Message *msg = &msgs;
                    723:     register struct type_SNMP_PDU *parm = msg -> data -> un.get__request;
                    724:     register struct type_SNMP_VarBindList  *vp = parm -> variable__bindings,
                    725:                                           *vp2,
                    726:                                          **vpp;
                    727:     PE     pe = NULLPE,
                    728:            p = NULLPE;
                    729: 
                    730:     if (snmp_ready () == NOTOK)
                    731:        goto out;
                    732: 
                    733:     msg -> data -> offset = type_SNMP_PDUs_get__next__request;
                    734:     parm -> request__id = snmp_id;
                    735:     parm -> variable__bindings = s -> s_bindings;
                    736: 
                    737:     result = encode_SNMP_Message (&pe, 1, 0, NULLCP, msg);
                    738: 
                    739:     parm -> variable__bindings = vp;
                    740:     msg -> data -> offset = type_SNMP_PDUs_get__request;
                    741: 
                    742:     if (result == NOTOK) {
                    743:        snmp_diag (NULLCP, "encode_SNMP_Message: %s", PY_pepy);
                    744:        goto out;
                    745:     }
                    746:     result = NOTOK;
                    747: 
                    748:     msg = NULL, gotone = 0;
                    749:     for (retries = snmp_retries; retries > 0; ) {
                    750:        int     len;
                    751:        fd_set  rfds;
                    752: 
                    753:        if (debug > 1)
                    754:            print_SNMP_Message (pe, 1, NULLIP, NULLVP, NULLCP);
                    755:        len = ps -> ps_byteno;
                    756:        if (pe2ps (ps, pe) == NOTOK) {
                    757:            snmp_diag (NULLCP, "pe2ps: %s", ps_error (ps -> ps_errno));
                    758:            goto error_x;
                    759:        }
                    760:        if (debug > 0 && (len = ps -> ps_byteno - len) > 484)
                    761:            fprintf (stderr, "sent message of %d octets\n", len);
                    762: 
                    763:        FD_ZERO (&rfds);
                    764:        FD_SET (snmp_fd, &rfds);
                    765: 
                    766:        switch (xselect (snmp_fd + 1, &rfds, NULLFD, NULLFD, snmp_timeout)) {
                    767:            case NOTOK:
                    768:                snmp_diag ("failed", "xselect");
                    769:                goto error_x;
                    770: 
                    771:            default:
                    772:                if (FD_ISSET (snmp_fd, &rfds))
                    773:                    break;
                    774:                /* else fall... */
                    775:            case OK:
                    776:                retries--;
                    777:                continue;
                    778:        }
                    779: 
                    780:        if ((p = ps2pe (ps)) == NULLPE) {
                    781:            snmp_diag (NULLCP, "ps2pe: %s", ps_error (ps -> ps_errno));
                    782:            goto error_x;
                    783:        }
                    784:        if (decode_SNMP_Message (p, 1, NULLIP, NULLVP, &msg) == NOTOK) {
                    785:            snmp_diag (NULLCP, "decode_SNMP_Message: %s", PY_pepy);
                    786:            goto out;
                    787:        }
                    788:        if (debug > 1)
                    789:            print_SNMP_Message (p, 1, NULLIP, NULLVP, NULLCP);
                    790: 
                    791:        if (msg -> data -> offset != type_SNMP_PDUs_get__response) {
                    792:            snmp_diag (NULLCP, "unexpected message type %d",
                    793:                       msg -> data -> offset);
                    794:            goto out;
                    795:        }
                    796: 
                    797:        if ((parm = msg -> data -> un.get__response) -> request__id == snmp_id)
                    798:            break;
                    799: 
                    800:        if (msg)
                    801:            free_SNMP_Message (msg), msg = NULL;
                    802:        if (p)
                    803:            pe_free (p), p = NULLPE;
                    804: 
                    805:        gotone++;
                    806:     }
                    807:     if (retries <= 0) {
                    808:        snmp_diag (NULLCP,
                    809:                   "no %sresponse within %d retries of %s%d second%s each",
                    810:                   gotone ? "acceptable " : "", snmp_retries + gotone,
                    811:                   gotone ? "upto " : "",
                    812:                   snmp_timeout, snmp_timeout != 1 ? "s" : "");
                    813:        goto out;
                    814:     }
                    815: 
                    816:     if ((status = parm -> error__status) != int_SNMP_error__status_noError) {
                    817:        char   *cp = snmp_variable (parm, parm -> error__index);
                    818: 
                    819:        snmp_diag (NULLCP, cp ? "%s at position %d (%s)" : "%s at position %d",
                    820:                   snmp_error (status), parm -> error__index,
                    821:                   cp);
                    822:        goto out;
                    823:     }
                    824: 
                    825:     for (vp = s -> s_bindings, vpp = &parm -> variable__bindings;
                    826:             vp && (vp2 = *vpp);
                    827:             vp = vp -> next) {
                    828:        if (name2obj (vp -> VarBind -> name)
                    829:                != name2obj (vp2 -> VarBind -> name)) {
                    830:            *vpp = vp2 -> next;
                    831:            vp2 -> next = NULL;
                    832:            free_SNMP_VarBindList (vp2);
                    833:        }
                    834:        else
                    835:            vpp = &vp2 -> next;
                    836:     }
                    837:     if (vp) {
                    838:        snmp_diag (NULLCP, "missing variable in response");
                    839:        goto out;
                    840:     }
                    841:     else
                    842:        if (vp2 = *vpp) {
                    843:            if (debug > 0)
                    844:                fprintf (stderr, "too many responses starting with: %s\n",
                    845:                         oid2ode (vp2 -> VarBind -> name));
                    846: 
                    847:            *vpp = NULL;
                    848:            free_SNMP_VarBindList (vp2);
                    849:        }
                    850: 
                    851:     if (s -> s_bindings)
                    852:        free_SNMP_VarBindList (s -> s_bindings);
                    853:     if (s -> s_pe)
                    854:        pe_free (s -> s_pe);
                    855: 
                    856:     s -> s_bindings = parm -> variable__bindings;
                    857:     parm -> variable__bindings = NULL;
                    858:     s -> s_pe = p;
                    859:     p = NULLPE;
                    860: 
                    861:     result = OK;
                    862:     goto out;
                    863: 
                    864: error_x: ;
                    865:     if (ps)
                    866:        ps_free (ps), ps = NULLPS;
                    867:     if (snmp_fd != NOTOK)
                    868:        (void) close_udp_socket (snmp_fd), snmp_fd = NOTOK;
                    869: 
                    870: out: ;
                    871:     if (msg && msg != &msgs)
                    872:        free_SNMP_Message (msg);
                    873:     if (p)
                    874:        pe_free (p);
                    875:     if (pe)
                    876:        pe_free (pe);
                    877: 
                    878:     assign_number (&ERROR_node -> var_value, (AWKNUM) status);
                    879: 
                    880:     return result;
                    881: }
                    882: 
                    883: /*    DECODE */
                    884: 
                    885: static NODE *make_octet_node (base, len)
                    886: char   *base;
                    887: int    len;
                    888: {
                    889:     register char *bp,
                    890:                  *cp,
                    891:                  *ep;
                    892:     char   *s = "";
                    893:     register NODE *r;
                    894: 
                    895:     r = newnode (Node_val);
                    896:     emalloc (r -> stptr, char *, len * 3 + 1, "make_octet_node");
                    897:     bp = r -> stptr;
                    898:     for (ep = (cp = base) + len; cp < ep; cp++, s = ":") {
                    899:        (void) sprintf (bp, "%s%02x", s, *cp & 0xff);
                    900:        bp += strlen (bp);
                    901:     }
                    902:     *bp = NULL;                /* in case len == 0 */
                    903:     r -> stlen = bp - r -> stptr;
                    904:     r -> stref = 1;
                    905:     r -> flags |= STR | MALLOC;
                    906: 
                    907:     return r;
                    908: }
                    909: 
                    910: 
                    911: static int  f_integer (x, pe)
                    912: NODE  **x;
                    913: PE     pe;
                    914: {
                    915:     integer    i = prim2num (pe);
                    916: 
                    917:     if (i == NOTOK && pe -> pe_errno != PE_ERR_NONE) {
                    918:        (void) strcpy (PY_pepy, pe_error (pe -> pe_errno));
                    919:        return NOTOK;
                    920:     }
                    921: 
                    922:     *x = make_number ((AWKNUM) i);
                    923: 
                    924:     return OK;
                    925: }
                    926: 
                    927: 
                    928: static int  f_octets (x, pe)
                    929: NODE  **x;
                    930: PE     pe;
                    931: {
                    932:     struct qbuf *qb = prim2qb (pe);
                    933: 
                    934:     if (qb == NULL|| qb_pullup (qb) == NOTOK) {
                    935:        (void) strcpy (PY_pepy, qb ? "qb_pullup: out of memory"
                    936:                                   : pe_error (pe -> pe_errno));
                    937:        return NOTOK;
                    938:     }
                    939: 
                    940:     *x = make_octet_node (qb -> qb_forw -> qb_data, qb -> qb_forw -> qb_len);
                    941: 
                    942:     qb_free (qb);
                    943: 
                    944:     return OK;
                    945: }
                    946: 
                    947: 
                    948: static int  f_display (x, pe)
                    949: NODE  **x;
                    950: PE     pe;
                    951: {
                    952:     struct qbuf *qb = prim2qb (pe);
                    953: 
                    954:     if (qb == NULL|| qb_pullup (qb) == NOTOK) {
                    955:        (void) strcpy (PY_pepy, qb ? "qb_pullup: out of memory"
                    956:                                   : pe_error (pe -> pe_errno));
                    957:        return NOTOK;
                    958:     }
                    959: 
                    960:     *x = make_string (qb -> qb_forw -> qb_data, qb -> qb_forw -> qb_len);
                    961: 
                    962:     qb_free (qb);
                    963: 
                    964:     return OK;
                    965: }
                    966: 
                    967: 
                    968: static int  f_objectID (x, pe)
                    969: NODE  **x;
                    970: PE     pe;
                    971: {
                    972:     char   *cp;
                    973:     OID            oid = prim2oid (pe);
                    974: 
                    975:     if (oid == NULLOID) {
                    976:        (void) strcpy (PY_pepy, pe_error (pe -> pe_errno));
                    977:        return NOTOK;
                    978:     }
                    979:     cp = sprintoid (oid);
                    980: 
                    981:     *x = make_string (cp, strlen (cp));
                    982: 
                    983:     return OK;
                    984: }
                    985: 
                    986: 
                    987: /* ARGSUSED */
                    988: 
                    989: static int  f_null (x, pe)
                    990: NODE  **x;
                    991: PE     pe;
                    992: {
                    993:     *x = make_str_node ("NULL", 4, 0);
                    994: 
                    995:     return OK;
                    996: }
                    997: 
                    998: 
                    999: static int  f_ipaddr (x, pe)
                   1000: NODE  **x;
                   1001: PE     pe;
                   1002: {
                   1003:     char    ipaddr[16];
                   1004:     struct type_SNMP_IpAddress *ip;
                   1005:     struct qbuf *qb;
                   1006: 
                   1007:     if (decode_SNMP_IpAddress (pe, 1, NULLIP, NULLVP, &ip) == NOTOK)
                   1008:        return NOTOK;
                   1009:     if (qb_pullup (ip) == NOTOK) {
                   1010:        (void) strcpy (PY_pepy, "qb_pullup: out of memory");
                   1011:        free_SNMP_IpAddress (ip);
                   1012:        return NOTOK;
                   1013:     }
                   1014:     if ((qb = ip -> qb_forw) -> qb_len != 4) {
                   1015:        (void) sprintf (PY_pepy,
                   1016:                        "IpAddress is wrong length (got %d, wanted 4)",
                   1017:                        qb -> qb_len);
                   1018:        free_SNMP_IpAddress (ip);
                   1019:        return NOTOK;
                   1020:     }
                   1021:     (void) sprintf (ipaddr, "%d.%d.%d.%d",
                   1022:                    qb -> qb_data[0] & 0xff, qb -> qb_data[1] & 0xff,
                   1023:                    qb -> qb_data[2] & 0xff, qb -> qb_data[3] & 0xff);
                   1024: 
                   1025:     *x = make_str_node (ipaddr, strlen (ipaddr), 0);
                   1026: 
                   1027:     free_SNMP_IpAddress (ip);
                   1028: 
                   1029:     return OK;
                   1030: }
                   1031: 
                   1032: 
                   1033: static int  f_clnpaddr (x, pe)
                   1034: NODE  **x;
                   1035: PE     pe;
                   1036: {
                   1037:     int            len;
                   1038:     struct type_SNMP_ClnpAddress *clnp;
                   1039:     struct qbuf *qb;
                   1040: 
                   1041:     if (decode_SNMP_ClnpAddress (pe, 1, NULLIP, NULLVP, &clnp) == NOTOK)
                   1042:        return NOTOK;
                   1043:     if (qb_pullup (clnp) == NOTOK) {
                   1044:        (void) strcpy (PY_pepy, "qb_pullup: out of memory");
                   1045:        free_SNMP_ClnpAddress (clnp);
                   1046:        return NOTOK;
                   1047:     }
                   1048:     qb = clnp -> qb_forw;
                   1049:     if ((len = qb -> qb_data[0] & 0xff) >= qb -> qb_len)
                   1050:        len = qb -> qb_len - 1;
                   1051: 
                   1052:     *x = make_octet_node (qb -> qb_data, len);
                   1053: 
                   1054:     free_SNMP_ClnpAddress (clnp);
                   1055: 
                   1056:     return OK;
                   1057: }
                   1058: 
                   1059: /*    MISC */
                   1060: 
                   1061: char   *snmp_name (ptr)
                   1062: NODE   *ptr;
                   1063: {
                   1064:     return ((OT) (ptr -> magic)) -> ot_text;
                   1065: }
                   1066: 
                   1067: /*  */
                   1068: 
                   1069: static char *errors[] = {
                   1070:     "noError", "tooBig", "noSuchName", "badValue", "readOnly", "genErr"
                   1071: };
                   1072: 
                   1073: 
                   1074: static char *snmp_error (i)
                   1075: int    i;
                   1076: {
                   1077:     static char buffer[BUFSIZ];
                   1078: 
                   1079:     if (0 < i && i < sizeof errors / sizeof errors[0])
                   1080:        return errors[i];
                   1081:     (void) sprintf (buffer, "error %d", i);
                   1082: 
                   1083:     return buffer;
                   1084: }
                   1085: 
                   1086: 
                   1087: static char *snmp_variable (parm, index)
                   1088: register struct type_SNMP_PDU *parm;
                   1089: int    index;
                   1090: {
                   1091:     register struct type_SNMP_VarBindList *vp;
                   1092: 
                   1093:     if (index <= 0 || (vp = parm -> variable__bindings) == NULL)
                   1094:        return NULL;
                   1095:     for (index--; index > 0; index--)
                   1096:        if ((vp = vp -> next) == NULL)
                   1097:            return NULL;
                   1098: 
                   1099:     return oid2ode (vp -> VarBind -> name);
                   1100: }
                   1101: #endif /* SNMP */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.