# BRCM_VERSION=3
[bcm963xx.git] / userapps / opensource / net-snmp / agent / mibgroup / target / snmpTargetAddrEntry.c
1 /*
2  * snmpTargetAddrEntry MIB
3  * 
4  * This file was generated by mib2c and is intended for use as a mib module
5  * for the ucd-snmp snmpd agent. Edited by Michael Baer
6  * 
7  * last changed 2/2/99.
8  */
9
10 #include <net-snmp/net-snmp-config.h>
11 #if HAVE_STRING_H
12 #include <string.h>
13 #else
14 #include <strings.h>
15 #endif
16 #include <stdlib.h>
17 #include <ctype.h>
18 #if HAVE_WINSOCK_H
19 #include <winsock.h>
20 #endif
21
22 #include <net-snmp/net-snmp-includes.h>
23 #include <net-snmp/agent/net-snmp-agent-includes.h>
24
25 #include "snmpTargetAddrEntry.h"
26 #include "util_funcs.h"
27
28 #define snmpTargetAddrOIDLen 11 /*This is base+column, 
29                                  * i.e. everything but index */
30
31 oid             snmpTargetAddrOID[snmpTargetAddrOIDLen] =
32     { 1, 3, 6, 1, 6, 3, 12, 1, 2, 1, 0 };
33
34 static unsigned long snmpTargetSpinLock = 0;
35 static struct targetAddrTable_struct *aAddrTable = 0;
36
37
38 /*
39  * Utility routines 
40  */
41 struct targetAddrTable_struct *
42 get_addrTable(void)
43 {
44     return aAddrTable;
45 }
46
47 struct targetAddrTable_struct *
48 get_addrForName(char *name)
49 {
50     struct targetAddrTable_struct *ptr;
51     for (ptr = aAddrTable; ptr != NULL; ptr = ptr->next) {
52         if (ptr->name && strcmp(ptr->name, name) == 0)
53             return ptr;
54     }
55     return NULL;
56 }
57
58
59 /*
60  * TargetAddrTable_create creates and returns a pointer
61  * to a targetAddrTable_struct with default values set 
62  */
63 struct targetAddrTable_struct
64                *
65 snmpTargetAddrTable_create(void)
66 {
67     struct targetAddrTable_struct *newEntry;
68
69     newEntry = (struct targetAddrTable_struct *)
70         malloc(sizeof(struct targetAddrTable_struct));
71
72     if (newEntry) {
73         newEntry->name = 0;
74
75         newEntry->tDomainLen = 0;
76         newEntry->tAddress = 0;
77
78         newEntry->timeout = 1500;
79         newEntry->retryCount = 3;
80
81         newEntry->tagList = strdup("");
82         newEntry->params = 0;
83
84         newEntry->storageType = SNMP_STORAGE_NONVOLATILE;
85         newEntry->rowStatus = SNMP_ROW_NONEXISTENT;
86         newEntry->sess = (netsnmp_session *) NULL;
87         newEntry->next = 0;
88     }
89
90     return newEntry;
91 }                               /* snmpTargetAddrTable_create */
92
93
94 /*
95  * TargetAddrTable_dispose frees the space allocated to a
96  * targetAddrTable_struct 
97  */
98 void
99 snmpTargetAddrTable_dispose(struct targetAddrTable_struct *reaped)
100 {
101     SNMP_FREE(reaped->name);
102     SNMP_FREE(reaped->tAddress);
103     SNMP_FREE(reaped->tagList);
104     SNMP_FREE(reaped->params);
105
106     SNMP_FREE(reaped);
107 }                               /* snmpTargetAddrTable_dispose  */
108
109 /*
110  * snmpTargetAddrTable_addToList adds a targetAddrTable_struct 
111  * to a list passed in. The list is assumed to be in a sorted order,
112  * low to high and this procedure inserts a new struct in the proper 
113  * location. Sorting uses OID values based on name. A new equal value 
114  * overwrites a current one. 
115  */
116 void
117 snmpTargetAddrTable_addToList(struct targetAddrTable_struct *newEntry,
118                               struct targetAddrTable_struct **listPtr)
119 {
120     static struct targetAddrTable_struct *curr_struct, *prev_struct;
121     int             i;
122     size_t          newOIDLen = 0, currOIDLen = 0;
123     oid             newOID[128], currOID[128];
124
125     /*
126      * if the list is empty, add the new entry to the top 
127      */
128     if ((prev_struct = curr_struct = *listPtr) == 0) {
129         *listPtr = newEntry;
130         return;
131     } else {
132         /*
133          * get the 'OID' value of the new entry 
134          */
135         newOIDLen = strlen(newEntry->name);
136         for (i = 0; i < (int) newOIDLen; i++) {
137             newOID[i] = newEntry->name[i];
138         }
139
140         /*
141          * search through the list for an equal or greater OID value 
142          */
143         while (curr_struct != 0) {
144             currOIDLen = strlen(curr_struct->name);
145             for (i = 0; i < (int) currOIDLen; i++) {
146                 currOID[i] = curr_struct->name[i];
147             }
148
149             i = snmp_oid_compare(newOID, newOIDLen, currOID, currOIDLen);
150             if (i == 0) {       /* Exact match, overwrite with new struct */
151                 newEntry->next = curr_struct->next;
152                 /*
153                  * if curr_struct is the top of the list 
154                  */
155                 if (*listPtr == curr_struct)
156                     *listPtr = newEntry;
157                 else
158                     prev_struct->next = newEntry;
159                 snmpTargetAddrTable_dispose(curr_struct);
160                 return;
161             } else if (i < 0) { /* Found a greater OID, insert struct in front of it. */
162                 newEntry->next = curr_struct;
163                 /*
164                  * if curr_struct is the top of the list 
165                  */
166                 if (*listPtr == curr_struct)
167                     *listPtr = newEntry;
168                 else
169                     prev_struct->next = newEntry;
170                 return;
171             }
172             prev_struct = curr_struct;
173             curr_struct = curr_struct->next;
174         }
175     }
176     /*
177      * if we're here, no larger OID was ever found, insert on end of list 
178      */
179     prev_struct->next = newEntry;
180 }                               /* snmpTargeAddrTable_addToList  */
181
182
183 void
184 snmpTargetAddrTable_add(struct targetAddrTable_struct *newEntry)
185 {
186     snmpTargetAddrTable_addToList(newEntry, &aAddrTable);
187 }
188
189
190 /*
191  * snmpTargetAddrTable_remFromList removes a targetAddrTable_struct 
192  * from the list passed in 
193  */
194 void
195 snmpTargetAddrTable_remFromList(struct targetAddrTable_struct *oldEntry,
196                                 struct targetAddrTable_struct **listPtr)
197 {
198     struct targetAddrTable_struct *tptr;
199
200     if ((tptr = *listPtr) == 0)
201         return;
202     else if (tptr == oldEntry) {
203         *listPtr = (*listPtr)->next;
204         snmpTargetAddrTable_dispose(tptr);
205         return;
206     } else {
207         while (tptr->next != 0) {
208             if (tptr->next == oldEntry) {
209                 tptr->next = tptr->next->next;
210                 snmpTargetAddrTable_dispose(oldEntry);
211                 return;
212             }
213             tptr = tptr->next;
214         }
215     }
216 }                               /* snmpTargetAddrTable_remFromList  */
217
218
219 /*
220  * lookup OID in the link list of Addr Table Entries 
221  */
222 struct targetAddrTable_struct *
223 search_snmpTargetAddrTable(oid * baseName,
224                            size_t baseNameLen,
225                            oid * name, size_t * length, int exact)
226 {
227     static struct targetAddrTable_struct *temp_struct;
228     int             i;
229     size_t          myOIDLen = 0;
230     oid             newNum[128];
231
232     /*
233      * lookup entry in addrTable linked list, Get Current MIB ID 
234      */
235     memcpy(newNum, baseName, baseNameLen * sizeof(oid));
236
237     for (temp_struct = aAddrTable; temp_struct != 0;
238          temp_struct = temp_struct->next) {
239         for (i = 0; i < (int) strlen(temp_struct->name); i++) {
240             newNum[baseNameLen + i] = temp_struct->name[i];
241         }
242         myOIDLen = baseNameLen + strlen(temp_struct->name);
243         i = snmp_oid_compare(name, *length, newNum, myOIDLen);
244         /*
245          * Assumes that the linked list sorted by OID, low to high 
246          */
247         if ((i == 0 && exact != 0) || (i < 0 && exact == 0)) {
248             if (exact == 0) {
249                 memcpy(name, newNum, myOIDLen * sizeof(oid));
250                 *length = myOIDLen;
251             }
252             return temp_struct;
253         }
254     }
255     return (0);
256 }                               /* search_snmpTargetAddrTable  */
257
258
259 /*
260  * snmpTargetAddr_rowStatusCheck is boolean funciton that  checks 
261  * the status of a row's values in order to determine whether
262  * the row should be notReady or notInService  
263  */
264 int
265 snmpTargetAddr_rowStatusCheck(struct targetAddrTable_struct *entry)
266 {
267     if ((entry->tDomainLen == 0) || (entry->tAddress == 0) ||
268         (entry->params == 0))
269         return 0;
270     else
271         return 1;
272 }                               /* snmtpTargetAddrTable_rowStatusCheck */
273
274
275 /*
276  * Init routines 
277  */
278
279 /*
280  * this variable defines function callbacks and type return information 
281  * for the snmpTargetAddrEntry mib 
282  */
283
284 struct variable2 snmpTargetAddrEntry_variables[] = {
285     {SNMPTARGETADDRTDOMAIN, ASN_OBJECT_ID, RWRITE,
286      var_snmpTargetAddrEntry, 1, {SNMPTARGETADDRTDOMAINCOLUMN}},
287     {SNMPTARGETADDRTADDRESS, ASN_OCTET_STR, RWRITE,
288      var_snmpTargetAddrEntry, 1, {SNMPTARGETADDRTADDRESSCOLUMN}},
289     {SNMPTARGETADDRTIMEOUT, ASN_INTEGER, RWRITE,
290      var_snmpTargetAddrEntry, 1, {SNMPTARGETADDRTIMEOUTCOLUMN}},
291     {SNMPTARGETADDRRETRYCOUNT, ASN_INTEGER, RWRITE,
292      var_snmpTargetAddrEntry, 1, {SNMPTARGETADDRRETRYCOUNTCOLUMN}},
293     {SNMPTARGETADDRTAGLIST, ASN_OCTET_STR, RWRITE,
294      var_snmpTargetAddrEntry, 1, {SNMPTARGETADDRTAGLISTCOLUMN}},
295     {SNMPTARGETADDRPARAMS, ASN_OCTET_STR, RWRITE,
296      var_snmpTargetAddrEntry, 1, {SNMPTARGETADDRPARAMSCOLUMN}},
297     {SNMPTARGETADDRSTORAGETYPE, ASN_INTEGER, RWRITE,
298      var_snmpTargetAddrEntry, 1, {SNMPTARGETADDRSTORAGETYPECOLUMN}},
299     {SNMPTARGETADDRROWSTATUS, ASN_INTEGER, RWRITE,
300      var_snmpTargetAddrEntry, 1, {SNMPTARGETADDRROWSTATUSCOLUMN}},
301
302 };
303
304 struct variable2 snmpTargetSpinLock_var[] = {
305     {SNMPTARGETSPINLOCK, ASN_INTEGER, RWRITE, var_targetSpinLock, 1, {1}}
306 };
307
308 static oid      snmpTargetSpinLock_oid[] = { 1, 3, 6, 1, 6, 3, 12, 1 };
309
310 /*
311  * now load this mib into the agents mib table 
312  */
313 oid             snmpTargetAddrEntry_variables_oid[] =
314     { 1, 3, 6, 1, 6, 3, 12, 1, 2, 1 };
315
316
317 void
318 init_snmpTargetAddrEntry(void)
319 {
320     aAddrTable = 0;
321     DEBUGMSGTL(("snmpTargetAddrEntry", "init\n"));
322     REGISTER_MIB("target/snmpTargetAddrEntry",
323                  snmpTargetAddrEntry_variables, variable2,
324                  snmpTargetAddrEntry_variables_oid);
325     REGISTER_MIB("target/snmpTargetSpinLock", snmpTargetSpinLock_var,
326                  variable2, snmpTargetSpinLock_oid);
327
328     snmpd_register_config_handler("targetAddr",
329                                   snmpd_parse_config_targetAddr, 0, NULL);
330
331     /*
332      * we need to be called back later 
333      */
334     snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
335                            store_snmpTargetAddrEntry, NULL);
336
337 }                               /* init_snmpTargetAddrEntry */
338
339
340 int
341 snmpTargetAddr_addName(struct targetAddrTable_struct *entry, char *cptr)
342 {
343     size_t          len;
344     if (cptr == 0) {
345         DEBUGMSGTL(("snmpTargetAddrEntry",
346                     "ERROR snmpTargetAddrEntry: no name in config string\n"));
347         return (0);
348     } else {
349         len = strlen(cptr);
350         /*
351          * spec check for string 1-32 
352          */
353         if (len < 1 || len > 32) {
354             DEBUGMSGTL(("snmpTargetAddrEntry",
355                         "ERROR snmpTargetAddrEntry: name out of range in config string\n"));
356             return (0);
357         }
358         entry->name = (char *) malloc(len + 1);
359         strncpy(entry->name, cptr, len);
360         entry->name[len] = '\0';
361     }
362     return (1);
363 }                               /* addName */
364
365
366 int
367 snmpTargetAddr_addTDomain(struct targetAddrTable_struct *entry, char *cptr)
368 {
369     size_t          len = 128;
370
371     if (cptr == 0) {
372         DEBUGMSGTL(("snmpTargetAddrEntry",
373                     "ERROR snmpTargetAddrEntry: no tDomain in config string\n"));
374         return (0);
375     }
376
377     if (!read_objid(cptr, entry->tDomain, &len)) {
378         DEBUGMSGTL(("snmpTargetAddrEntry",
379                     "ERROR snmpTargetAddrEntry: tDomain unreadable in config string\n"));
380         return (0);
381     }
382
383     /*
384      * spec check for oid 1-128 
385      */
386     if (len < 1 || len > 128) {
387         DEBUGMSGTL(("snmpTargetAddrEntry",
388                     "ERROR snmpTargetAddrEntry: tDomain out of range in config string\n"));
389         return (0);
390     }
391
392     entry->tDomainLen = len;
393     return (1);
394 }                               /* snmpTargetAddr_addTDomain */
395
396
397 int
398 snmpTargetAddr_addTAddress(struct targetAddrTable_struct *entry,
399                            char *cptr, size_t len)
400 {
401     if (cptr == 0) {
402         DEBUGMSGTL(("snmpTargetAddrEntry",
403                     "ERROR snmpTargetAddrEntry: no tAddress in config string\n"));
404         return (0);
405     } else {
406         /*
407          * spec check for string 1-32 
408          */
409         /*
410          * if (len < 1 || len > 32)  {
411          * DEBUGMSGTL(("snmpTargetAddrEntry","ERROR snmpTargetAddrEntry: name out of range in config string\n"));
412          * return(0);
413          * } 
414          */
415         SNMP_FREE(entry->tAddress);
416         entry->tAddress = (u_char *) malloc(len);
417         entry->tAddressLen = len;
418         memcpy(entry->tAddress, cptr, len);
419     }
420     return (1);
421 }                               /* snmpTargetAddr_addTAddress */
422
423
424 int
425 snmpTargetAddr_addTimeout(struct targetAddrTable_struct *entry, char *cptr)
426 {
427     if (cptr == 0) {
428         DEBUGMSGTL(("snmpTargetAddrEntry",
429                     "ERROR snmpTargetParamsEntry: no Timeout in config string\n"));
430         return (0);
431     } else if (!(isdigit(*cptr))) {
432         DEBUGMSGTL(("snmpTargetAddrEntry",
433                     "ERROR snmpTargeParamsEntry: Timeout is not a digit in config string\n"));
434         return (0);
435     }
436     /*
437      * check Timeout >= 0 
438      */
439     else if ((entry->timeout = (int) strtol(cptr, (char **) NULL, 0)) < 0) {
440         DEBUGMSGTL(("snmpTargetAddrEntry",
441                     "ERROR snmpTargeParamsEntry: Timeout out of range in config string\n"));
442         return (0);
443     }
444     return (1);
445 }                               /* snmpTargetAddr_addTimeout  */
446
447
448 int
449 snmpTargetAddr_addRetryCount(struct targetAddrTable_struct *entry,
450                              char *cptr)
451 {
452     if (cptr == 0) {
453         DEBUGMSGTL(("snmpTargetAddrEntry",
454                     "ERROR snmpTargetParamsEntry: no Retry Count in config string\n"));
455         return (0);
456     } else if (!(isdigit(*cptr))) {
457         DEBUGMSGTL(("snmpTargetAddrEntry",
458                     "ERROR snmpTargeParamsEntry: Retry Count is not a digit in config string\n"));
459         return (0);
460     }
461     /*
462      * spec check 0..255 
463      */
464     else {
465         entry->retryCount = (int) strtol(cptr, (char **) NULL, 0);
466         if ((entry->retryCount < 0) || (entry->retryCount > 255)) {
467             DEBUGMSGTL(("snmpTargetAddrEntry",
468                         "ERROR snmpTargeParamsEntry: Retry Count is out of range in config string\n"));
469             return (0);
470         }
471     }
472     return (1);
473 }                               /* snmpTargetAddr_addRetryCount  */
474
475
476 int
477 snmpTargetAddr_addTagList(struct targetAddrTable_struct *entry, char *cptr)
478 {
479     size_t          len;
480     if (cptr == 0) {
481         DEBUGMSGTL(("snmpTargetAddrEntry",
482                     "ERROR snmpTargetAddrEntry: no tag list in config string\n"));
483         return (0);
484     } else {
485         len = strlen(cptr);
486         /*
487          * spec check for string 0-255 
488          */
489         if (len < 0 || len > 255) {
490             DEBUGMSGTL(("snmpTargetAddrEntry",
491                         "ERROR snmpTargetAddrEntry: tag list out of range in config string\n"));
492             return (0);
493         }
494         SNMP_FREE(entry->tagList);
495         entry->tagList = (char *) malloc(len + 1);
496         strncpy(entry->tagList, cptr, len);
497         entry->tagList[len] = '\0';
498     }
499     return (1);
500 }                               /* snmpTargetAddr_addTagList */
501
502
503 int
504 snmpTargetAddr_addParams(struct targetAddrTable_struct *entry, char *cptr)
505 {
506     size_t          len;
507     if (cptr == 0) {
508         DEBUGMSGTL(("snmpTargetAddrEntry",
509                     "ERROR snmpTargetAddrEntry: no params in config string\n"));
510         return (0);
511     } else {
512         len = strlen(cptr);
513         /*
514          * spec check for string 1-32 
515          */
516         if (len < 1 || len > 32) {
517             DEBUGMSGTL(("snmpTargetAddrEntry",
518                         "ERROR snmpTargetAddrEntry: params out of range in config string\n"));
519             return (0);
520         }
521         entry->params = (char *) malloc(len + 1);
522         strncpy(entry->params, cptr, len);
523         entry->params[len] = '\0';
524     }
525     return (1);
526 }                               /* snmpTargetAddr_addParams */
527
528
529 int
530 snmpTargetAddr_addStorageType(struct targetAddrTable_struct *entry,
531                               char *cptr)
532 {
533     char            buff[1024];
534
535     if (cptr == 0) {
536         DEBUGMSGTL(("snmpTargetAddrEntry",
537                     "ERROR snmpTargetAddrEntry: no storage type in config string\n"));
538         return (0);
539     } else if (!(isdigit(*cptr))) {
540         DEBUGMSGTL(("snmpTargetAddrEntry",
541                     "ERROR snmpTargetAddrEntry: storage type is not a digit in config string\n"));
542         return (0);
543     }
544     /*
545      * check that storage type is a possible value 
546      */
547     else if (((entry->storageType = (int) strtol(cptr, (char **) NULL, 0))
548               != SNMP_STORAGE_OTHER) &&
549              (entry->storageType != SNMP_STORAGE_VOLATILE) &&
550              (entry->storageType != SNMP_STORAGE_NONVOLATILE) &&
551              (entry->storageType != SNMP_STORAGE_PERMANENT) &&
552              (entry->storageType != SNMP_STORAGE_READONLY)) {
553         snprintf(buff, sizeof(buff),
554                 "ERROR snmpTargetAddrEntry: storage type not a valid value of other(%d), volatile(%d), nonvolatile(%d), permanent(%d), or readonly(%d) in config string.\n",
555                 SNMP_STORAGE_OTHER, SNMP_STORAGE_VOLATILE,
556                 SNMP_STORAGE_NONVOLATILE, SNMP_STORAGE_PERMANENT,
557                 SNMP_STORAGE_READONLY);
558         buff[ sizeof(buff)-1 ] = 0;
559         DEBUGMSGTL(("snmpTargetAddrEntry", buff));
560
561         return (0);
562     }
563     return (1);
564 }                               /* snmpTargetAddr_addStorageType */
565
566
567 int
568 snmpTargetAddr_addRowStatus(struct targetAddrTable_struct *entry,
569                             char *cptr)
570 {
571     char            buff[1024];
572
573     if (cptr == 0) {
574         DEBUGMSGTL(("snmpTargetAddrEntry",
575                     "ERROR snmpTargetAddrEntry: no Row Status in config string\n"));
576         return (0);
577     } else if (!(isdigit(*cptr))) {
578         DEBUGMSGTL(("snmpTargetAddrEntry",
579                     "ERROR snmpTargetAddrEntry: Row Status is not a digit in config string\n"));
580         return (0);
581     }
582     /*
583      * check that row status is a valid value 
584      */
585     else if (((entry->rowStatus = (int) strtol(cptr, (char **) NULL, 0))
586               != SNMP_ROW_ACTIVE) &&
587              (entry->rowStatus != SNMP_ROW_NOTINSERVICE) &&
588              (entry->rowStatus != SNMP_ROW_NOTREADY)) {
589         snprintf(buff, sizeof(buff),
590                 "ERROR snmpTargetAddrEntry: Row Status is not a valid value of active(%d), notinservice(%d), or notready(%d) in config string.\n",
591                 SNMP_ROW_ACTIVE, SNMP_ROW_NOTINSERVICE, SNMP_ROW_NOTREADY);
592         buff[ sizeof(buff)-1 ] = 0;
593         DEBUGMSGTL(("snmpTargetAddrEntry", buff));
594
595         return (0);
596     }
597     return (1);
598 }                               /* snmpTargetAddr_addRowStatus  */
599
600
601 void
602 snmpd_parse_config_targetAddr(const char *token, char *char_ptr)
603 {
604     char           *cptr = char_ptr, buff[1024];
605     struct targetAddrTable_struct *newEntry;
606     int             i;
607
608     newEntry = snmpTargetAddrTable_create();
609
610     cptr = copy_nword(cptr, buff, sizeof(buff));
611     if (snmpTargetAddr_addName(newEntry, buff) == 0) {
612         snmpTargetAddrTable_dispose(newEntry);
613         return;
614     }
615     cptr = copy_nword(cptr, buff, sizeof(buff));
616     if (snmpTargetAddr_addTDomain(newEntry, buff) == 0) {
617         snmpTargetAddrTable_dispose(newEntry);
618         return;
619     }
620     cptr =
621         read_config_read_octet_string(cptr,
622                                       (u_char **) & newEntry->tAddress,
623                                       &newEntry->tAddressLen);
624     if (!cptr || !(newEntry->tAddress)) {
625         DEBUGMSGTL(("snmpTargetAddrEntry",
626                     "ERROR snmpTargetAddrEntry: no TAddress in config string\n"));
627         snmpTargetAddrTable_dispose(newEntry);
628         return;
629     }
630     cptr = copy_nword(cptr, buff, sizeof(buff));
631     if (snmpTargetAddr_addTimeout(newEntry, buff) == 0) {
632         snmpTargetAddrTable_dispose(newEntry);
633         return;
634     }
635     cptr = copy_nword(cptr, buff, sizeof(buff));
636     if (snmpTargetAddr_addRetryCount(newEntry, buff) == 0) {
637         snmpTargetAddrTable_dispose(newEntry);
638         return;
639     }
640     cptr = copy_nword(cptr, buff, sizeof(buff));
641     if (snmpTargetAddr_addTagList(newEntry, buff) == 0) {
642         snmpTargetAddrTable_dispose(newEntry);
643         return;
644     }
645     cptr = copy_nword(cptr, buff, sizeof(buff));
646     if (snmpTargetAddr_addParams(newEntry, buff) == 0) {
647         snmpTargetAddrTable_dispose(newEntry);
648         return;
649     }
650     cptr = copy_nword(cptr, buff, sizeof(buff));
651     if (snmpTargetAddr_addStorageType(newEntry, buff) == 0) {
652         snmpTargetAddrTable_dispose(newEntry);
653         return;
654     }
655     cptr = copy_nword(cptr, buff, sizeof(buff));
656     if (snmpTargetAddr_addRowStatus(newEntry, buff) == 0) {
657         snmpTargetAddrTable_dispose(newEntry);
658         return;
659     }
660     snprintf(buff, sizeof(buff), "snmp_parse_config_targetAddr, read: %s\n",
661             newEntry->name);
662     buff[ sizeof(buff)-1 ] = 0;
663     for (i = 0; i < newEntry->tDomainLen; i++) {
664         snprintf(&buff[strlen(buff)], sizeof(buff)-strlen(buff)-1,
665                  ".%d", (int) newEntry->tDomain[i]);
666         buff[ sizeof(buff)-1 ] = 0;
667     }
668     snprintf(&buff[strlen(buff)], sizeof(buff)-strlen(buff)-1,
669             " %s %d %d %s %s %d %d\n",
670             newEntry->tAddress, newEntry->timeout, newEntry->retryCount,
671             newEntry->tagList, newEntry->params, newEntry->storageType,
672             newEntry->rowStatus);
673     buff[ sizeof(buff)-1 ] = 0;
674     DEBUGMSGTL(("snmpTargetAddrEntry", buff));
675
676     snmpTargetAddrTable_addToList(newEntry, &aAddrTable);
677 }                               /* snmpd_parse_config_target */
678
679
680 /*
681  * Shutdown routines 
682  */
683
684
685 /*
686  * store_snmpTargetAddrEntry handles the persistent storage proccess 
687  * for this MIB table. It writes out all the non-volatile rows 
688  * to permanent storage on a shutdown  
689  */
690 int
691 store_snmpTargetAddrEntry(int majorID, int minorID, void *serverarg,
692                           void *clientarg)
693 {
694     struct targetAddrTable_struct *curr_struct;
695     char            line[1024];
696     int             i;
697
698     if ((curr_struct = aAddrTable) != 0) {
699         while (curr_struct != 0) {
700             if ((curr_struct->storageType == SNMP_STORAGE_NONVOLATILE ||
701                  curr_struct->storageType == SNMP_STORAGE_PERMANENT)
702                 &&
703                 (curr_struct->rowStatus == SNMP_ROW_ACTIVE ||
704                  curr_struct->rowStatus == SNMP_ROW_NOTINSERVICE)) {
705                 snprintf(line, sizeof(line),
706                         "targetAddr %s ", curr_struct->name);
707                 line[ sizeof(line)-1 ] = 0;
708                 for (i = 0; i < curr_struct->tDomainLen; i++) {
709                     snprintf(&line[strlen(line)],
710                             sizeof(line)-strlen(line)-1, ".%i",
711                             (int) curr_struct->tDomain[i]);
712                     line[ sizeof(line)-1 ] = 0;
713                 }
714                 if ( strlen(line)+2 < sizeof(line) ) {
715                     line[ strlen(line)+1 ] = 0;
716                     line[ strlen(line)   ] = ' ';
717                 }
718                 read_config_save_octet_string(&line[strlen(line)],
719                                               curr_struct->tAddress,
720                                               curr_struct->tAddressLen);
721
722                 snprintf(&line[strlen(line)], sizeof(line)-strlen(line)-1,
723                         " %i %i \"%s\" %s %i %i",
724                         curr_struct->timeout,
725                         curr_struct->retryCount, curr_struct->tagList,
726                         curr_struct->params, curr_struct->storageType,
727                         curr_struct->rowStatus);
728                 line[ sizeof(line)-1 ] = 0;
729
730                 /*
731                  * store to file 
732                  */
733                 snmpd_store_config(line);
734             }
735             curr_struct = curr_struct->next;
736         }
737     }
738     return SNMPERR_SUCCESS;
739
740 }                               /*  store_snmpTargetAddrEntry  */
741
742
743 /*
744  * MIB table access routines 
745  */
746
747
748 u_char         *
749 var_snmpTargetAddrEntry(struct variable * vp,
750                         oid * name,
751                         size_t * length,
752                         int exact,
753                         size_t * var_len, WriteMethod ** write_method)
754 {
755
756     /*
757      * variables we may use later 
758      */
759     static long     long_ret;
760     static char     string[1500];
761     static oid      objid[128];
762     struct targetAddrTable_struct *temp_struct;
763     int             i = 0;
764
765     /*
766      * Set up write_method first, in case we return NULL before getting to the
767      * switch (vp->magic) below.  In some of these cases, we still want to call
768      * the appropriate write_method, if only to have it return the appropriate
769      * error.  
770      */
771
772     switch (vp->magic) {
773     case SNMPTARGETADDRTDOMAIN:
774         *write_method = write_snmpTargetAddrTDomain;
775         break;
776     case SNMPTARGETADDRTADDRESS:
777         *write_method = write_snmpTargetAddrTAddress;
778         break;
779     case SNMPTARGETADDRRETRYCOUNT:
780         *write_method = write_snmpTargetAddrRetryCount;
781         break;
782     case SNMPTARGETADDRTIMEOUT:
783         *write_method = write_snmpTargetAddrTimeout;
784         break;
785     case SNMPTARGETADDRTAGLIST:
786         *write_method = write_snmpTargetAddrTagList;
787         break;
788     case SNMPTARGETADDRPARAMS:
789         *write_method = write_snmpTargetAddrParams;
790         break;
791     case SNMPTARGETADDRSTORAGETYPE:
792         *write_method = write_snmpTargetAddrStorageType;
793         break;
794     case SNMPTARGETADDRROWSTATUS:
795         *write_method = write_snmpTargetAddrRowStatus;
796         break;
797     default:
798         *write_method = NULL;
799     }
800
801     *var_len = sizeof(long_ret);        /* assume an integer and change later if not */
802
803     /*
804      * look for OID in current table 
805      */
806     if ((temp_struct = search_snmpTargetAddrTable(vp->name, vp->namelen,
807                                                   name, length,
808                                                   exact)) == 0) {
809         return (0);
810     }
811
812     /*
813      * We found what we were looking for, either the next OID or the exact OID 
814      */
815     /*
816      * this is where we do the value assignments for the mib results. 
817      */
818     switch (vp->magic) {
819     case SNMPTARGETADDRTDOMAIN:
820         if (temp_struct->tDomainLen <= 0) {
821             return (0);
822         } else {
823             for (i = 0; i < temp_struct->tDomainLen; i++) {
824                 objid[i] = temp_struct->tDomain[i];
825             }
826             *var_len = temp_struct->tDomainLen * sizeof(oid);
827         }
828         return (unsigned char *) objid;
829
830     case SNMPTARGETADDRTADDRESS:
831         if (temp_struct->tAddress == 0)
832             return (0);
833         *var_len = temp_struct->tAddressLen;
834         return (unsigned char *) temp_struct->tAddress;
835
836     case SNMPTARGETADDRTIMEOUT:
837         long_ret = temp_struct->timeout;
838         return (unsigned char *) &long_ret;
839
840     case SNMPTARGETADDRRETRYCOUNT:
841         long_ret = temp_struct->retryCount;
842         return (unsigned char *) &long_ret;
843
844     case SNMPTARGETADDRTAGLIST:
845         if (temp_struct->tagList != NULL) {
846             strcpy(string, temp_struct->tagList);
847             *var_len = strlen(string);
848             return (unsigned char *) string;
849         } else {
850             return NULL;
851         }
852
853     case SNMPTARGETADDRPARAMS:
854         if (temp_struct->params == 0)
855             return (0);
856         strcpy(string, temp_struct->params);
857         *var_len = strlen(string);
858         return (unsigned char *) string;
859
860     case SNMPTARGETADDRSTORAGETYPE:
861         long_ret = temp_struct->storageType;
862         return (unsigned char *) &long_ret;
863
864     case SNMPTARGETADDRROWSTATUS:
865         long_ret = temp_struct->rowStatus;
866         return (unsigned char *) &long_ret;
867
868     default:
869         DEBUGMSGTL(("snmpd",
870                     "unknown sub-id %d in var_snmpTargetAddrEntry\n",
871                     vp->magic));
872     }
873     return 0;
874 }                               /* var_snmpTargetAddrEntry */
875
876
877 int
878 write_snmpTargetAddrTDomain(int action,
879                             u_char * var_val,
880                             u_char var_val_type,
881                             size_t var_val_len,
882                             u_char * statP, oid * name, size_t name_len)
883 {
884     struct targetAddrTable_struct *target = NULL;
885     static oid      old_oid[MAX_OID_LEN];
886     static size_t   old_oid_len;
887
888     if (action == RESERVE1) {
889         if (var_val_type != ASN_OBJECT_ID) {
890             DEBUGMSGTL(("snmpTargetAddrEntry",
891                         "write to snmpTargetAddrTDomain not ASN_OBJECT_ID\n"));
892             return SNMP_ERR_WRONGTYPE;
893         }
894         if ((var_val_len > (MAX_OID_LEN * sizeof(oid))) ||
895             (var_val_len % sizeof(oid) != 0)) {
896             DEBUGMSGTL(("snmpTargetAddrEntry",
897                         "write to snmpTargetAddrTDomain: bad length\n"));
898             return SNMP_ERR_WRONGLENGTH;
899         }
900     } else if (action == RESERVE2) {
901         snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
902             SNMPTARGETADDRTDOMAINCOLUMN;
903         if ((target =
904              search_snmpTargetAddrTable(snmpTargetAddrOID,
905                                         snmpTargetAddrOIDLen, name,
906                                         &name_len, 1)) == 0) {
907             DEBUGMSGTL(("snmpTargetAddrEntry",
908                         "write to snmpTargetAddrTDomain: BAD OID!\n"));
909             return SNMP_ERR_INCONSISTENTNAME;
910         } else {
911             if (target->storageType == SNMP_STORAGE_READONLY) {
912                 DEBUGMSGTL(("snmpTargetAddrEntry",
913                             "write to snmpTargetAddrTDomain: row is read only\n"));
914                 return SNMP_ERR_NOTWRITABLE;
915             }
916             if (target->rowStatus == SNMP_ROW_ACTIVE) {
917                 DEBUGMSGTL(("snmpTargetAddrEntry",
918                             "write to snmpTargetAddrTDomain: not allowed in active row.\n"));
919                 return SNMP_ERR_INCONSISTENTVALUE;
920             }
921
922             /*
923              * Finally, we're golden, save current value.  
924              */
925
926             memcpy(old_oid, target->tDomain,
927                    target->tDomainLen * sizeof(oid));
928             old_oid_len = target->tDomainLen;
929
930             memcpy((u_char *) target->tDomain, var_val, var_val_len);
931             target->tDomainLen = var_val_len / sizeof(oid);
932
933             /*
934              * If row is new, check if its status can be updated.  
935              */
936             if ((target->rowStatus == SNMP_ROW_NOTREADY) &&
937                 (snmpTargetAddr_rowStatusCheck(target) != 0)) {
938                 target->rowStatus = SNMP_ROW_NOTINSERVICE;
939             }
940         }
941     } else if (action == FREE || action == UNDO) {
942         /*
943          * Try to undo the SET here (abnormal usage of FREE clause)  
944          */
945         snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
946             SNMPTARGETADDRTDOMAINCOLUMN;
947         if ((target =
948              search_snmpTargetAddrTable(snmpTargetAddrOID,
949                                         snmpTargetAddrOIDLen, name,
950                                         &name_len, 1)) != NULL) {
951             if (target->storageType != SNMP_STORAGE_READONLY
952                 && target->rowStatus != SNMP_ROW_ACTIVE) {
953                 memcpy((u_char *) target->tDomain, (u_char *) old_oid,
954                        (old_oid_len * sizeof(oid)));
955                 target->tDomainLen = old_oid_len;
956                 if (target->rowStatus == SNMP_ROW_NOTINSERVICE &&
957                     snmpTargetAddr_rowStatusCheck(target) == 0) {
958                     target->rowStatus = SNMP_ROW_NOTREADY;
959                 }
960             }
961         }
962     }
963     return SNMP_ERR_NOERROR;
964 }                               /* write_snmpTargetAddrTDomain */
965
966
967 int
968 write_snmpTargetAddrTAddress(int action,
969                              u_char * var_val,
970                              u_char var_val_type,
971                              size_t var_val_len,
972                              u_char * statP, oid * name, size_t name_len)
973 {
974     struct targetAddrTable_struct *target = NULL;
975     static char    *old_addr = NULL;
976     static size_t   old_len = 0;
977
978     if (action == RESERVE1) {
979         if (var_val_type != ASN_OCTET_STR) {
980             DEBUGMSGTL(("snmpTargetAddrEntry",
981                         "write to snmpTargetAddrTAddress not ASN_OCTET_STR\n"));
982             return SNMP_ERR_WRONGTYPE;
983         } else if (var_val_len < 1 || var_val_len > 255) {
984             return SNMP_ERR_WRONGLENGTH;
985         }
986     } else if (action == RESERVE2) {
987         snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
988             SNMPTARGETADDRTADDRESSCOLUMN;
989         if ((target =
990              search_snmpTargetAddrTable(snmpTargetAddrOID,
991                                         snmpTargetAddrOIDLen, name,
992                                         &name_len, 1)) == 0) {
993             DEBUGMSGTL(("snmpTargetAddrEntry",
994                         "write to snmpTargetAddrTAddress: BAD OID!\n"));
995             return SNMP_ERR_INCONSISTENTNAME;
996         } else {
997             if (target->storageType == SNMP_STORAGE_READONLY) {
998                 DEBUGMSGTL(("snmpTargetAddrEntry",
999                             "write to snmpTargetAddrTAddress: row is read only\n"));
1000                 return SNMP_ERR_NOTWRITABLE;
1001             }
1002             if (target->rowStatus == SNMP_ROW_ACTIVE) {
1003                 DEBUGMSGTL(("snmpTargetAddrEntry",
1004                             "write to snmpTargetAddrTAddress: not allowed in active row.\n"));
1005                 return SNMP_ERR_INCONSISTENTVALUE;
1006             }
1007
1008             old_addr = target->tAddress;
1009             old_len = target->tAddressLen;
1010             target->tAddress = (u_char *) malloc(var_val_len);
1011             if (target->tAddress == NULL) {
1012                 return SNMP_ERR_RESOURCEUNAVAILABLE;
1013             }
1014             memcpy(target->tAddress, var_val, var_val_len);
1015             target->tAddressLen = var_val_len;
1016
1017             /*
1018              * If row is new, check if its status can be updated.  
1019              */
1020             if ((target->rowStatus == SNMP_ROW_NOTREADY) &&
1021                 (snmpTargetAddr_rowStatusCheck(target) != 0)) {
1022                 target->rowStatus = SNMP_ROW_NOTINSERVICE;
1023             }
1024         }
1025     } else if (action == COMMIT) {
1026         SNMP_FREE(old_addr);
1027         old_addr = NULL;
1028     } else if (action == FREE || action == UNDO) {
1029         /*
1030          * Try to undo the SET here (abnormal usage of FREE clause)  
1031          */
1032         snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
1033             SNMPTARGETADDRTADDRESSCOLUMN;
1034         if ((target =
1035              search_snmpTargetAddrTable(snmpTargetAddrOID,
1036                                         snmpTargetAddrOIDLen, name,
1037                                         &name_len, 1)) != NULL) {
1038             if (target->storageType != SNMP_STORAGE_READONLY
1039                 && target->rowStatus != SNMP_ROW_ACTIVE) {
1040                 SNMP_FREE(target->tAddress);
1041                 target->tAddress = old_addr;
1042                 target->tAddressLen = old_len;
1043                 if (target->rowStatus == SNMP_ROW_NOTINSERVICE &&
1044                     snmpTargetAddr_rowStatusCheck(target) == 0) {
1045                     target->rowStatus = SNMP_ROW_NOTREADY;
1046                 }
1047             }
1048         }
1049     }
1050
1051     return SNMP_ERR_NOERROR;
1052 }                               /* write_snmpTargetAddrTAddress */
1053
1054
1055 int
1056 write_snmpTargetAddrTimeout(int action,
1057                             u_char * var_val,
1058                             u_char var_val_type,
1059                             size_t var_val_len,
1060                             u_char * statP, oid * name, size_t name_len)
1061 {
1062     /*
1063      * variables we may use later 
1064      */
1065     static long     long_ret;
1066     size_t          size;
1067     struct targetAddrTable_struct *temp_struct;
1068
1069     if (action == RESERVE1) {
1070         if (var_val_type != ASN_INTEGER) {
1071             DEBUGMSGTL(("snmpTargetAddrEntry",
1072                         "write to snmpTargetAddrTimeout not ASN_INTEGER\n"));
1073             return SNMP_ERR_WRONGTYPE;
1074         }
1075         if (var_val_len > (size = sizeof(long_ret))) {
1076             DEBUGMSGTL(("snmpTargetAddrEntry",
1077                         "write to snmpTargetAddrTimeout: bad length\n"));
1078             return SNMP_ERR_WRONGLENGTH;
1079         }
1080         long_ret = *((long *) var_val);
1081     } else if (action == RESERVE2) {
1082
1083         /*
1084          * spec check range, no spec check 
1085          */
1086
1087         /*
1088          * Find row in linked list and check pertinent status... 
1089          */
1090         snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
1091             SNMPTARGETADDRTIMEOUTCOLUMN;
1092         if ((temp_struct =
1093              search_snmpTargetAddrTable(snmpTargetAddrOID,
1094                                         snmpTargetAddrOIDLen, name, &name_len,
1095                                         1)) == 0) {
1096             DEBUGMSGTL(("snmpTargetAddrEntry",
1097                         "write to snmpTargetAddrTimeout : BAD OID\n"));
1098             return SNMP_ERR_NOSUCHNAME;
1099         }
1100         /*
1101          * row exists, check if it is changeable 
1102          */
1103         if (temp_struct->storageType == SNMP_STORAGE_READONLY) {
1104             DEBUGMSGTL(("snmpTargetAddrEntry",
1105                         "write to snmpTargetAddrTimeout : row is read only\n"));
1106             return SNMP_ERR_NOTWRITABLE;
1107         }
1108     } else if  (action == COMMIT) {
1109         /*
1110          * Finally, we're golden, should we save value? 
1111          */
1112         snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
1113             SNMPTARGETADDRTIMEOUTCOLUMN;
1114         if ((temp_struct =
1115              search_snmpTargetAddrTable(snmpTargetAddrOID,
1116                                         snmpTargetAddrOIDLen, name, &name_len,
1117                                         1)) == 0) {
1118             temp_struct->timeout = long_ret;
1119         }
1120     }
1121
1122     return SNMP_ERR_NOERROR;
1123 }                               /* write_snmpTargetAddrTimeout */
1124
1125
1126 int
1127 write_snmpTargetAddrRetryCount(int action,
1128                                u_char * var_val,
1129                                u_char var_val_type,
1130                                size_t var_val_len,
1131                                u_char * statP, oid * name, size_t name_len)
1132 {
1133     static long     long_ret;
1134     struct targetAddrTable_struct *target;
1135
1136     if (action == RESERVE1) {
1137         if (var_val_type != ASN_INTEGER) {
1138             DEBUGMSGTL(("snmpTargetAddrEntry",
1139                         "write to snmpTargetAddrRetryCount not ASN_INTEGER\n"));
1140             return SNMP_ERR_WRONGTYPE;
1141         }
1142         if (var_val_len != sizeof(long)) {
1143             DEBUGMSGTL(("snmpTargetAddrEntry",
1144                         "write to snmpTargetAddrRetryCount: bad length\n"));
1145             return SNMP_ERR_WRONGLENGTH;
1146         }
1147         long_ret = *((long *) var_val);
1148         if (long_ret < 0 || long_ret > 255) {
1149             return SNMP_ERR_WRONGVALUE;
1150         }
1151     } else if (action == RESERVE2) {
1152         snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
1153             SNMPTARGETADDRRETRYCOUNTCOLUMN;
1154         if ((target = search_snmpTargetAddrTable(snmpTargetAddrOID,
1155                                                  snmpTargetAddrOIDLen,
1156                                                  name, &name_len,
1157                                                  1)) == NULL) {
1158             DEBUGMSGTL(("snmpTargetAddrEntry",
1159                         "write to snmpTargetAddrTimeout: BAD OID\n"));
1160             return SNMP_ERR_INCONSISTENTNAME;
1161         } else {
1162             if (target->storageType == SNMP_STORAGE_READONLY) {
1163                 DEBUGMSGTL(("snmpTargetAddrEntry",
1164                             "write to snmpTargetAddrRetryCount: row is read only\n"));
1165                 return SNMP_ERR_NOTWRITABLE;
1166             }
1167         }
1168     } else if (action == COMMIT) {
1169         snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
1170             SNMPTARGETADDRRETRYCOUNTCOLUMN;
1171         if ((target = search_snmpTargetAddrTable(snmpTargetAddrOID,
1172                                                  snmpTargetAddrOIDLen,
1173                                                  name, &name_len,
1174                                                  1)) != NULL) {
1175             target->retryCount = long_ret;
1176         }
1177     }
1178
1179     return SNMP_ERR_NOERROR;
1180 }                               /* write_snmpTargetAddrRetryCount */
1181
1182 static int
1183 is_delim(const char c)
1184 {
1185     return (c == 0x020 || c == 0x09 || c == 0x0d || c == 0x0b);
1186 }
1187
1188 int
1189 snmpTagListValid(const char *tagList, const size_t tagListLen)
1190 {
1191     size_t          i = 0;
1192     int             inTag = 0;
1193
1194
1195     for (i = 0; i < tagListLen; i++) {
1196         if (is_delim(tagList[i]) && !inTag) {
1197             /*
1198              * Either a leading delimiter or two consecutive delimiters.  
1199              */
1200             return 0;
1201         } else if (is_delim(tagList[i]) && inTag) {
1202             inTag = 0;
1203         } else if (!is_delim(tagList[i]) && !inTag) {
1204             inTag = 1;
1205         }
1206     }
1207     if (!inTag) {
1208         /*
1209          * Trailing delimiter.  
1210          */
1211         return 0;
1212     }
1213     return 1;
1214 }
1215
1216 int
1217 write_snmpTargetAddrTagList(int action,
1218                             u_char * var_val,
1219                             u_char var_val_type,
1220                             size_t var_val_len,
1221                             u_char * statP, oid * name, size_t name_len)
1222 {
1223     struct targetAddrTable_struct *target = NULL;
1224     static char    *old_tlist;
1225
1226     if (action == RESERVE1) {
1227         if (var_val_type != ASN_OCTET_STR) {
1228             DEBUGMSGTL(("snmpTargetAddrEntry",
1229                         "write to snmpTargetAddrTagList not ASN_OCTET_STR\n"));
1230             return SNMP_ERR_WRONGTYPE;
1231         }
1232         if (var_val_len > 255) {
1233             DEBUGMSGTL(("snmpTargetAddrEntry",
1234                         "write to snmpTargetAddrTagList: bad length\n"));
1235             return SNMP_ERR_WRONGLENGTH;
1236         }
1237         if (!snmpTagListValid(var_val, var_val_len)) {
1238             return SNMP_ERR_WRONGVALUE;
1239         }
1240     } else if (action == RESERVE2) {
1241         snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
1242             SNMPTARGETADDRTAGLISTCOLUMN;
1243         if ((target =
1244              search_snmpTargetAddrTable(snmpTargetAddrOID,
1245                                         snmpTargetAddrOIDLen, name,
1246                                         &name_len, 1)) == NULL) {
1247             DEBUGMSGTL(("snmpTargetAddrEntry",
1248                         "write to snmpTargetAddrTagList: BAD OID!\n"));
1249             return SNMP_ERR_INCONSISTENTNAME;
1250         } else {
1251             if (target->storageType == SNMP_STORAGE_READONLY) {
1252                 DEBUGMSGTL(("snmpTargetAddrEntry",
1253                             "write to snmpTargetAddrTagList: row is read only\n"));
1254                 return SNMP_ERR_NOTWRITABLE;
1255             }
1256             old_tlist = target->tagList;
1257             target->tagList = (char *) malloc(var_val_len + 1);
1258             if (target->tagList == NULL) {
1259                 return SNMP_ERR_RESOURCEUNAVAILABLE;
1260             }
1261             memcpy(target->tagList, var_val, var_val_len);
1262             target->tagList[var_val_len] = '\0';
1263         }
1264     } else if (action == COMMIT) {
1265         SNMP_FREE(old_tlist);
1266         old_tlist = NULL;
1267     } else if (action == FREE || action == UNDO) {
1268         snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
1269             SNMPTARGETADDRTAGLISTCOLUMN;
1270         if ((target =
1271              search_snmpTargetAddrTable(snmpTargetAddrOID,
1272                                         snmpTargetAddrOIDLen, name,
1273                                         &name_len, 1)) != NULL) {
1274             if (target->storageType != SNMP_STORAGE_READONLY) {
1275                 SNMP_FREE(target->tagList);
1276                 target->tagList = old_tlist;
1277             }
1278         }
1279     }
1280
1281     return SNMP_ERR_NOERROR;
1282 }                               /* write_snmpTargetAddrTagList */
1283
1284
1285 int
1286 write_snmpTargetAddrParams(int action,
1287                            u_char * var_val,
1288                            u_char var_val_type,
1289                            size_t var_val_len,
1290                            u_char * statP, oid * name, size_t name_len)
1291 {
1292     struct targetAddrTable_struct *target = NULL;
1293     static char    *old_params = NULL;
1294
1295     if (action == RESERVE1) {
1296         if (var_val_type != ASN_OCTET_STR) {
1297             DEBUGMSGTL(("snmpTargetAddrEntry",
1298                         "write to snmpTargetAddrParams not ASN_OCTET_STR\n"));
1299             return SNMP_ERR_WRONGTYPE;
1300         } else if (var_val_len < 1 || var_val_len > 32) {
1301             return SNMP_ERR_WRONGLENGTH;
1302         }
1303     } else if (action == RESERVE2) {
1304         snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
1305             SNMPTARGETADDRPARAMSCOLUMN;
1306         if ((target =
1307              search_snmpTargetAddrTable(snmpTargetAddrOID,
1308                                         snmpTargetAddrOIDLen, name,
1309                                         &name_len, 1)) == 0) {
1310             DEBUGMSGTL(("snmpTargetAddrEntry",
1311                         "write to snmpTargetAddrParams: BAD OID!\n"));
1312             return SNMP_ERR_INCONSISTENTNAME;
1313         } else {
1314             if (target->storageType == SNMP_STORAGE_READONLY) {
1315                 DEBUGMSGTL(("snmpTargetAddrEntry",
1316                             "write to snmpTargetAddrParams: row is read only\n"));
1317                 return SNMP_ERR_NOTWRITABLE;
1318             }
1319             if (target->rowStatus == SNMP_ROW_ACTIVE) {
1320                 DEBUGMSGTL(("snmpTargetAddrEntry",
1321                             "write to snmpTargetAddrParams: not allowed in active row.\n"));
1322                 return SNMP_ERR_INCONSISTENTVALUE;
1323             }
1324
1325             old_params = target->params;
1326             target->params = (u_char *) malloc(var_val_len + 1);
1327             if (target->params == NULL) {
1328                 return SNMP_ERR_RESOURCEUNAVAILABLE;
1329             }
1330             memcpy(target->params, var_val, var_val_len);
1331             target->params[var_val_len] = '\0';
1332
1333             /*
1334              * If row is new, check if its status can be updated.  
1335              */
1336             if ((target->rowStatus == SNMP_ROW_NOTREADY) &&
1337                 (snmpTargetAddr_rowStatusCheck(target) != 0)) {
1338                 target->rowStatus = SNMP_ROW_NOTINSERVICE;
1339             }
1340         }
1341     } else if (action == COMMIT) {
1342         SNMP_FREE(old_params);
1343         old_params = NULL;
1344     } else if (action == FREE || action == UNDO) {
1345         /*
1346          * Try to undo the SET here (abnormal usage of FREE clause)  
1347          */
1348         snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
1349             SNMPTARGETADDRPARAMSCOLUMN;
1350         if ((target =
1351              search_snmpTargetAddrTable(snmpTargetAddrOID,
1352                                         snmpTargetAddrOIDLen, name,
1353                                         &name_len, 1)) != NULL) {
1354             if (target->storageType != SNMP_STORAGE_READONLY
1355                 && target->rowStatus != SNMP_ROW_ACTIVE) {
1356                 SNMP_FREE(target->params);
1357                 target->params = old_params;
1358                 if (target->rowStatus == SNMP_ROW_NOTINSERVICE &&
1359                     snmpTargetAddr_rowStatusCheck(target) == 0) {
1360                     target->rowStatus = SNMP_ROW_NOTREADY;
1361                 }
1362             }
1363         }
1364     }
1365
1366     return SNMP_ERR_NOERROR;
1367 }                               /* write_snmpTargetAddrParams */
1368
1369 int
1370 write_snmpTargetAddrStorageType(int action,
1371                                 u_char * var_val,
1372                                 u_char var_val_type,
1373                                 size_t var_val_len,
1374                                 u_char * statP,
1375                                 oid * name, size_t name_len)
1376 {
1377     long            long_ret = *((long *) var_val);
1378     struct targetAddrTable_struct *target;
1379
1380     if (action == RESERVE1) {
1381         if (var_val_type != ASN_INTEGER) {
1382             DEBUGMSGTL(("snmpTargetAddrEntry",
1383                         "write to snmpTargetAddrStorageType not ASN_INTEGER\n"));
1384             return SNMP_ERR_WRONGTYPE;
1385         }
1386         if (var_val_len != sizeof(long)) {
1387             DEBUGMSGTL(("snmpTargetAddrEntry",
1388                         "write to snmpTargetAddrStorageType: bad length\n"));
1389             return SNMP_ERR_WRONGLENGTH;
1390         }
1391         if (long_ret != SNMP_STORAGE_OTHER &&
1392             long_ret != SNMP_STORAGE_VOLATILE &&
1393             long_ret != SNMP_STORAGE_NONVOLATILE) {
1394             DEBUGMSGTL(("snmpTargetAddrEntry",
1395                         "write to snmpTargetAddrStorageType: attempted storage type not a valid"));
1396             DEBUGMSG(("snmpTargetAddrEntry",
1397                       " value of other(%d), volatile(%d), or nonvolatile(%d)\n",
1398                       SNMP_STORAGE_OTHER, SNMP_STORAGE_VOLATILE,
1399                       SNMP_STORAGE_NONVOLATILE));
1400             return SNMP_ERR_WRONGVALUE;
1401         }
1402     } else if (action == RESERVE2) {
1403         snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
1404             SNMPTARGETADDRSTORAGETYPECOLUMN;
1405         if ((target = search_snmpTargetAddrTable(snmpTargetAddrOID,
1406                                                  snmpTargetAddrOIDLen,
1407                                                  name, &name_len,
1408                                                  1)) == NULL) {
1409             DEBUGMSGTL(("snmpTargetAddrEntry",
1410                         "write to snmpTargetAddrStorageType: BAD OID\n"));
1411             return SNMP_ERR_INCONSISTENTNAME;
1412         } else {
1413             if (target->storageType == SNMP_STORAGE_PERMANENT ||
1414                 target->storageType == SNMP_STORAGE_READONLY) {
1415                 DEBUGMSGTL(("snmpTargetAddrEntry",
1416                             "write to snmpTargetAddrStorageType: row has unchangeable storage status: %d\n",
1417                             target->storageType));
1418                 return SNMP_ERR_WRONGVALUE;
1419             }
1420         }
1421     } else if (action == COMMIT) {
1422         snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
1423             SNMPTARGETADDRSTORAGETYPECOLUMN;
1424         if ((target = search_snmpTargetAddrTable(snmpTargetAddrOID,
1425                                                  snmpTargetAddrOIDLen,
1426                                                  name, &name_len,
1427                                                  1)) != NULL) {
1428             target->storageType = long_ret;
1429         }
1430     }
1431
1432     return SNMP_ERR_NOERROR;
1433 }                               /* write_snmpTargetAddrStorageType */
1434
1435
1436 /*
1437  * snmpTargeAddr_createNewRow is called from write_snmpTargetAddrRowStatus
1438  * when a new row is required. It creates a new row with 
1439  * the index of the passed in 'name' (i.e. full index OID) and
1440  * adds it to the linked list. 'name' should be the full OID of the new index. 
1441  * It passes back 0 if unsuccessfull.
1442  */
1443 int
1444 snmpTargetAddr_createNewRow(oid * name, size_t name_len)
1445 {
1446     size_t          newNameLen;
1447     int             i;
1448     struct targetAddrTable_struct *temp_struct;
1449
1450     /*
1451      * setup a new snmpTargetAddrTable structure and add it to the list 
1452      */
1453     newNameLen = name_len - snmpTargetAddrOIDLen;
1454     if (newNameLen > 0) {
1455         temp_struct = snmpTargetAddrTable_create();
1456         temp_struct->name = (char *) malloc(newNameLen + 1);
1457         if (temp_struct->name == NULL) {
1458             return 0;
1459         }
1460
1461         for (i = 0; i < (int) newNameLen; i++) {
1462             temp_struct->name[i] = (char) name[i + snmpTargetAddrOIDLen];
1463         }
1464
1465         temp_struct->name[newNameLen] = '\0';
1466         temp_struct->rowStatus = SNMP_ROW_NOTREADY;
1467
1468         snmpTargetAddrTable_addToList(temp_struct, &aAddrTable);
1469
1470         return 1;
1471     }
1472
1473     return 0;
1474 }                               /* snmpTargetAddr_createNewRow */
1475
1476
1477 /*
1478  * Assign a value to the Row Status variable 
1479  */
1480 int
1481 write_snmpTargetAddrRowStatus(int action,
1482                               u_char * var_val,
1483                               u_char var_val_type,
1484                               size_t var_val_len,
1485                               u_char * statP, oid * name, size_t name_len)
1486 {
1487     static long     value;
1488     struct targetAddrTable_struct *target = NULL;
1489
1490     if (action == RESERVE1) {
1491         value = *((long *) var_val);
1492         if (var_val_type != ASN_INTEGER) {
1493             DEBUGMSGTL(("snmpTargetAddrEntry",
1494                         "write to snmpTargetAddrRowStatus not ASN_INTEGER\n"));
1495             return SNMP_ERR_WRONGTYPE;
1496         }
1497         if (var_val_len != sizeof(int)) {
1498             DEBUGMSGTL(("snmpTargetAddrEntry",
1499                         "write to snmpTargetAddrRowStatus: bad length\n"));
1500             return SNMP_ERR_WRONGLENGTH;
1501         }
1502         if (value == RS_NOTREADY || value < 1 || value > 6) {
1503             return SNMP_ERR_WRONGVALUE;
1504         }
1505
1506         /*
1507          * Check index value is reasonable.  
1508          */
1509
1510         if (name_len < snmpTargetAddrOIDLen + 1 ||
1511             name_len > snmpTargetAddrOIDLen + 32) {
1512             DEBUGMSGTL(("snmpTargetAddrEntry", "bad index length %d\n",
1513                         name_len - snmpTargetAddrOIDLen));
1514             return SNMP_ERR_NOCREATION;
1515         }
1516
1517         /*
1518          * Search for struct in linked list.  
1519          */
1520
1521         snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
1522             SNMPTARGETADDRROWSTATUSCOLUMN;
1523         target =
1524             search_snmpTargetAddrTable(snmpTargetAddrOID,
1525                                        snmpTargetAddrOIDLen, name,
1526                                        &name_len, 1);
1527
1528         if (target != NULL) {
1529             if (value == RS_CREATEANDGO || value == RS_CREATEANDWAIT) {
1530                 value = RS_NOTREADY;
1531                 return SNMP_ERR_INCONSISTENTVALUE;
1532             }
1533             if (target->storageType == SNMP_STORAGE_READONLY) {
1534                 DEBUGMSGTL(("snmpTargetAddrEntry", "row is read only\n"));
1535                 return SNMP_ERR_NOTWRITABLE;
1536             }
1537             if (target->storageType == SNMP_STORAGE_PERMANENT) {
1538                 if (value == RS_DESTROY) {
1539                     DEBUGMSGTL(("snmpTargetAddrEntry",
1540                                 "unable to destroy permanent row\n"));
1541                     return SNMP_ERR_INCONSISTENTVALUE;
1542                 }
1543             }
1544         } else {
1545             if (value == RS_ACTIVE || value == RS_NOTINSERVICE) {
1546                 return SNMP_ERR_INCONSISTENTVALUE;
1547             }
1548             if (value == RS_CREATEANDGO || value == RS_CREATEANDWAIT) {
1549                 if (snmpTargetAddr_createNewRow(name, name_len) == 0) {
1550                     DEBUGMSGTL(("snmpTargetAddrEntry",
1551                                 "couldn't malloc() new row\n"));
1552                     return SNMP_ERR_RESOURCEUNAVAILABLE;
1553                 }
1554             }
1555         }
1556     } else if (action == ACTION) {
1557         snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
1558             SNMPTARGETADDRROWSTATUSCOLUMN;
1559         target =
1560             search_snmpTargetAddrTable(snmpTargetAddrOID,
1561                                        snmpTargetAddrOIDLen, name,
1562                                        &name_len, 1);
1563
1564         if (target != NULL) {
1565             if (value == RS_CREATEANDGO) {
1566                 /*
1567                  * Check whether all the required objects have been set.  
1568                  */
1569                 if (snmpTargetAddr_rowStatusCheck(target)) {
1570                     target->rowStatus = RS_ACTIVE;
1571                 } else {
1572                     target->rowStatus = RS_NOTREADY;
1573                 }
1574             } else if (value == RS_CREATEANDWAIT) {
1575                 /*
1576                  * Check whether all the required objects have been set.  
1577                  */
1578                 if (snmpTargetAddr_rowStatusCheck(target)) {
1579                     target->rowStatus = RS_NOTINSERVICE;
1580                 } else {
1581                     target->rowStatus = RS_NOTREADY;
1582                 }
1583             } else if (value == RS_ACTIVE) {
1584                 if (target->rowStatus == RS_NOTINSERVICE) {
1585                     target->rowStatus = RS_ACTIVE;
1586                 } else if (target->rowStatus == RS_NOTREADY) {
1587                     return SNMP_ERR_INCONSISTENTVALUE;
1588                 }
1589             } else if (value == RS_NOTINSERVICE) {
1590                 if (target->rowStatus == RS_ACTIVE) {
1591                     target->rowStatus = RS_NOTINSERVICE;
1592                 } else if (target->rowStatus == RS_NOTREADY) {
1593                     return SNMP_ERR_INCONSISTENTVALUE;
1594                 }
1595             }
1596         }
1597     } else if (action == COMMIT) {
1598         snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
1599             SNMPTARGETADDRROWSTATUSCOLUMN;
1600         target =
1601             search_snmpTargetAddrTable(snmpTargetAddrOID,
1602                                        snmpTargetAddrOIDLen, name,
1603                                        &name_len, 1);
1604         if (target != NULL) {
1605             if (value == RS_DESTROY) {
1606                 snmpTargetAddrTable_remFromList(target, &aAddrTable);
1607             }
1608             if (value == RS_NOTINSERVICE) {
1609                 if (target->sess != NULL) {
1610                     snmp_close(target->sess);
1611                     target->sess = NULL;
1612                 }
1613             }
1614         }
1615     } else if (action == UNDO || action == FREE) {
1616         snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
1617             SNMPTARGETADDRROWSTATUSCOLUMN;
1618         target =
1619             search_snmpTargetAddrTable(snmpTargetAddrOID,
1620                                        snmpTargetAddrOIDLen, name,
1621                                        &name_len, 1);
1622         if (value == RS_CREATEANDGO || value == RS_CREATEANDWAIT) {
1623             if (target != NULL) {
1624                 snmpTargetAddrTable_remFromList(target, &aAddrTable);
1625             }
1626         }
1627     }
1628     return SNMP_ERR_NOERROR;
1629 }                               /* write_snmpTargetAddrRowStatus */
1630
1631
1632
1633 int
1634 write_targetSpinLock(int action,
1635                      u_char * var_val,
1636                      u_char var_val_type,
1637                      size_t var_val_len,
1638                      u_char * statP, oid * name, size_t name_len)
1639 {
1640     if (action == RESERVE1) {
1641         if (var_val_type != ASN_INTEGER) {
1642             return SNMP_ERR_WRONGTYPE;
1643         }
1644         if (var_val_len != sizeof(unsigned long)) {
1645             return SNMP_ERR_WRONGLENGTH;
1646         }
1647         if (*((unsigned long *) var_val) != snmpTargetSpinLock) {
1648             return SNMP_ERR_INCONSISTENTVALUE;
1649         }
1650     } else if (action == COMMIT) {
1651         if (snmpTargetSpinLock == 2147483647) {
1652             snmpTargetSpinLock = 0;
1653         } else {
1654             snmpTargetSpinLock++;
1655         }
1656     }
1657     return SNMP_ERR_NOERROR;
1658 }
1659
1660
1661
1662 u_char         *
1663 var_targetSpinLock(struct variable * vp,
1664                    oid * name,
1665                    size_t * length,
1666                    int exact,
1667                    size_t * var_len, WriteMethod ** write_method)
1668 {
1669     if (header_generic(vp, name, length, exact, var_len, write_method) ==
1670         MATCH_FAILED) {
1671         *write_method = write_targetSpinLock;
1672         return NULL;
1673     }
1674     if (vp->magic == SNMPTARGETSPINLOCK) {
1675         *write_method = write_targetSpinLock;
1676         *var_len = sizeof(unsigned long);
1677         return (u_char *) & (snmpTargetSpinLock);
1678     }
1679     return NULL;
1680 }