1 /*
2  * pet.c
3  *
4  * MontaVista IPMI code handling for setting up and receiving platform
5  * event traps.
6  *
7  * Author: MontaVista Software, Inc.
8  *         Corey Minyard <minyard@mvista.com>
9  *         source@mvista.com
10  *
11  * Copyright 2004 MontaVista Software Inc.
12  *
13  *  This program is free software; you can redistribute it and/or
14  *  modify it under the terms of the GNU Lesser General Public License
15  *  as published by the Free Software Foundation; either version 2 of
16  *  the License, or (at your option) any later version.
17  *
18  *
19  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
20  *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25  *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
27  *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
28  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  *  You should have received a copy of the GNU Lesser General Public
31  *  License along with this program; if not, write to the Free
32  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
33  */
34 
35 /* NOTE: This code requires scan_sysaddr to be set for the BMC
36    connections. */
37 
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <netinet/in.h>
41 #include <errno.h>
42 #include <unistd.h>
43 #include <string.h>
44 #include <stdio.h>
45 
46 #include <OpenIPMI/os_handler.h>
47 #include <OpenIPMI/ipmi_err.h>
48 #include <OpenIPMI/ipmi_pet.h>
49 #include <OpenIPMI/ipmi_pef.h>
50 #include <OpenIPMI/ipmi_lanparm.h>
51 #include <OpenIPMI/ipmi_msgbits.h>
52 
53 #include <OpenIPMI/internal/ipmi_int.h>
54 #include <OpenIPMI/internal/locked_list.h>
55 #include <OpenIPMI/internal/ipmi_domain.h>
56 #include <OpenIPMI/internal/ipmi_mc.h>
57 
58 /* Recheck the PET config every 10 minutes. */
59 #define PET_TIMEOUT_SEC 600
60 
61 /* Time between alert retries (in seconds). */
62 #define IPMI_LANPARM_DEFAULT_ALERT_RETRY_TIMEOUT 1
63 
64 /* Alerts get retried this many times. */
65 #define IPMI_LANPARM_DEFAULT_ALERT_RETRIES 3
66 
67 #define IPMI_PET_ATTR_NAME "ipmi_pet"
68 
69 
70 /* This data structure defines a data/mask setting for a parameter,
71    either from the LAN or PEF parms. */
72 typedef struct parm_check_s
73 {
74     unsigned char conf_num; /* The number we are interested in. */
75     unsigned char set;      /* The specific selector. */
76     unsigned int  data_len; /* The length of the data we are using. */
77     unsigned char data[22]; /* The actual data. */
78     unsigned char mask[22]; /* The mask bits used to mask what we compare. */
79 } parm_check_t;
80 
81 /* Information for running the timer.  Note that there is no lock in
82    the timer, since the timer is only deleted when the pet_lock is
83    held write, we read-lock the pet timer to avoid locking problem. */
84 typedef struct pet_timer_s {
85     int          cancelled;
86     int          running;
87     os_handler_t *os_hnd;
88     ipmi_lock_t  *lock; /* Lock is here because we need it in the timer. */
89     ipmi_pet_t   *pet;
90     int          err;
91 } pet_timer_t;
92 
93 #define NUM_PEF_SETTINGS 4
94 #define NUM_LANPARM_SETTINGS 2
95 
96 struct ipmi_pet_s
97 {
98     int destroyed;
99     int in_list;
100 
101     unsigned int refcount;
102 
103     char name[IPMI_PET_NAME_LEN];
104 
105     /* Configuration parameters */
106     ipmi_mcid_t      mc;
107     ipmi_domain_id_t domain;
108     struct in_addr   ip_addr;
109     char             mac_addr[6];
110     unsigned int     policy_num;
111     unsigned int     eft_sel;
112     unsigned int     apt_sel;
113     unsigned int     lan_dest_sel;
114 
115     unsigned int channel;
116     ipmi_pet_t   *pet;
117     int          pef_err;
118     int          pef_lock_broken;
119     int          lanparm_err;
120     int          lanparm_lock_broken;
121     int          changed_lanparm;
122     int          changed_pef;
123 
124     int            lanparm_check_pos;
125     ipmi_lanparm_t *lanparm;
126 
127     int          pef_check_pos;
128     ipmi_pef_t   *pef;
129 
130     /* The domain's OS handler */
131     os_handler_t     *os_hnd;
132 
133     ipmi_pet_done_cb done;
134     void             *cb_data;
135 
136     ipmi_pet_done_cb destroy_done;
137     void             *destroy_cb_data;
138 
139     int              in_progress;
140 
141     /* The LAN configuration parameters to check. */
142     parm_check_t     lanparm_check[NUM_LANPARM_SETTINGS];
143 
144     /* The PEF configuration parameters to check */
145     parm_check_t     pef_check[NUM_PEF_SETTINGS];
146 
147     /* Timer to check the configuration periodically. */
148     pet_timer_t       *timer_info;
149     os_hnd_timer_id_t *timer;
150 };
151 
152 static void rescan_pet(void *cb_data, os_hnd_timer_id_t *id);
153 
154 static void
pet_lock(ipmi_pet_t * pet)155 pet_lock(ipmi_pet_t *pet)
156 {
157     ipmi_lock(pet->timer_info->lock);
158 }
159 
160 static void
pet_unlock(ipmi_pet_t * pet)161 pet_unlock(ipmi_pet_t *pet)
162 {
163     ipmi_unlock(pet->timer_info->lock);
164 }
165 
166 static void
internal_pet_destroy(ipmi_pet_t * pet)167 internal_pet_destroy(ipmi_pet_t *pet)
168 {
169     os_handler_t *os_hnd = pet->timer_info->os_hnd;
170 
171     if (pet->in_list) {
172 	ipmi_domain_attr_t *attr;
173 	locked_list_t      *pets;
174 	int                rv;
175 	rv = ipmi_domain_id_find_attribute(pet->domain,
176 					   IPMI_PET_ATTR_NAME, &attr);
177 	if (!rv) {
178 	    pet->refcount++;
179 	    pet->in_list = 0;
180 	    pet_unlock(pet);
181 
182 	    pets = ipmi_domain_attr_get_data(attr);
183 
184 	    locked_list_remove(pets, pet, NULL);
185 	    ipmi_domain_attr_put(attr);
186 	    pet_lock(pet);
187 	    /* While we were unlocked, someone may have come in and
188 	       grabbed the PET by iterating the list of PETs.  That's
189 	       ok, we just let them handle the destruction since this
190 	       code will not be entered again. */
191 	    if (pet->refcount != 1) {
192 		pet->refcount--;
193 		pet_unlock(pet);
194 		return;
195 	    }
196 	}
197     }
198     pet_unlock(pet);
199 
200     if (os_hnd->stop_timer(os_hnd, pet->timer) == 0) {
201 	ipmi_destroy_lock(pet->timer_info->lock);
202 	os_hnd->free_timer(os_hnd, pet->timer);
203 	ipmi_mem_free(pet->timer_info);
204     } else {
205 	pet->timer_info->cancelled = 1;
206     }
207 
208     if (pet->destroy_done) {
209 	pet->destroy_done(pet, 0, pet->destroy_cb_data);
210     }
211 
212     ipmi_mem_free(pet);
213 }
214 
215 static void
pet_get_nolock(ipmi_pet_t * pet)216 pet_get_nolock(ipmi_pet_t *pet)
217 {
218     pet->refcount++;
219 }
220 
221 static void
pet_get(ipmi_pet_t * pet)222 pet_get(ipmi_pet_t *pet)
223 {
224     pet_lock(pet);
225     pet_get_nolock(pet);
226     pet_unlock(pet);
227 }
228 
229 /* Be very careful, only call this when the refcount cannot go to zero. */
230 static void
pet_put_nolock(ipmi_pet_t * pet)231 pet_put_nolock(ipmi_pet_t *pet)
232 {
233     pet->refcount--;
234 }
235 
236 static void
pet_put_locked(ipmi_pet_t * pet)237 pet_put_locked(ipmi_pet_t *pet)
238 {
239     pet->refcount--;
240     if (pet->refcount == 0) {
241 	internal_pet_destroy(pet);
242 	return;
243     }
244     pet_unlock(pet);
245 }
246 
247 static void
pet_put(ipmi_pet_t * pet)248 pet_put(ipmi_pet_t *pet)
249 {
250     pet_lock(pet);
251     pet_put_locked(pet);
252 }
253 
254 void
ipmi_pet_ref(ipmi_pet_t * pet)255 ipmi_pet_ref(ipmi_pet_t *pet)
256 {
257     pet_get(pet);
258 }
259 
260 void
ipmi_pet_deref(ipmi_pet_t * pet)261 ipmi_pet_deref(ipmi_pet_t *pet)
262 {
263     pet_put(pet);
264 }
265 
266 static int
pet_attr_init(ipmi_domain_t * domain,void * cb_data,void ** data)267 pet_attr_init(ipmi_domain_t *domain, void *cb_data, void **data)
268 {
269     locked_list_t *pets;
270 
271     pets = locked_list_alloc(ipmi_domain_get_os_hnd(domain));
272     if (!pets)
273 	return ENOMEM;
274 
275     *data = pets;
276     return 0;
277 }
278 
279 static int
destroy_pet(void * cb_data,void * item1,void * item2)280 destroy_pet(void *cb_data, void *item1, void *item2)
281 {
282     ipmi_pet_t *pet = item1;
283 
284     pet_lock(pet);
285     pet->in_list = 0;
286     pet_unlock(pet);
287     return LOCKED_LIST_ITER_CONTINUE;
288 }
289 
290 static void
pet_attr_destroy(void * cb_data,void * data)291 pet_attr_destroy(void *cb_data, void *data)
292 {
293     locked_list_t *pets = data;
294 
295     locked_list_iterate(pets, destroy_pet, NULL);
296     locked_list_destroy(pets);
297 }
298 
299 /* Must be called locked, this will unlock the PET. */
300 static void
pet_op_done(ipmi_pet_t * pet)301 pet_op_done(ipmi_pet_t *pet)
302 {
303     struct timeval timeout;
304     os_handler_t   *os_hnd = pet->os_hnd;
305 
306     pet->in_progress--;
307 
308     if (pet->in_progress == 0) {
309 	if (pet->lanparm) {
310 	    ipmi_lanparm_destroy(pet->lanparm, NULL, NULL);
311 	    pet->lanparm = NULL;
312 	}
313 
314 	if (pet->done) {
315 	    ipmi_pet_done_cb done = pet->done;
316 	    void             *cb_data = pet->cb_data;
317 	    pet->done = NULL;
318 	    pet_unlock(pet);
319 	    done(pet, 0, cb_data);
320 	    pet_lock(pet);
321 	}
322 
323 	/* Restart the timer */
324 	timeout.tv_sec = PET_TIMEOUT_SEC;
325 	timeout.tv_usec = 0;
326 	os_hnd->start_timer(os_hnd, pet->timer, &timeout, rescan_pet,
327 			    pet->timer_info);
328 	pet->timer_info->running = 1;
329 
330     }
331 
332     pet_put_locked(pet);
333 }
334 
335 static void
lanparm_unlocked(ipmi_lanparm_t * lanparm,int err,void * cb_data)336 lanparm_unlocked(ipmi_lanparm_t *lanparm,
337 		 int            err,
338 		 void           *cb_data)
339 {
340     ipmi_pet_t *pet = cb_data;
341 
342     pet_lock(pet);
343     ipmi_lanparm_destroy(pet->lanparm, NULL, NULL);
344     pet->lanparm = NULL;
345     pet_op_done(pet);
346 }
347 
348 static void
lanparm_commited(ipmi_lanparm_t * lanparm,int err,void * cb_data)349 lanparm_commited(ipmi_lanparm_t *lanparm,
350 		 int            err,
351 		 void           *cb_data)
352 {
353     ipmi_pet_t    *pet = cb_data;
354     int           rv;
355     unsigned char data[1];
356 
357     pet_lock(pet);
358     if (pet->destroyed) {
359 	pet_op_done(pet);
360 	goto out;
361     }
362 
363     /* Ignore the error, committing is optional. */
364 
365     data[0] = 0; /* clear lock */
366     rv = ipmi_lanparm_set_parm(pet->lanparm, 0, data, 1,
367 			       lanparm_unlocked, pet);
368     if (rv) {
369 	ipmi_log(IPMI_LOG_WARNING,
370 		 "pet.c(lanparm_commited): error clearing lock: 0x%x", rv);
371 	ipmi_lanparm_destroy(pet->lanparm, NULL, NULL);
372 	pet->lanparm = NULL;
373 	pet_op_done(pet);
374 	goto out;
375     }
376     pet_unlock(pet);
377  out:
378     return;
379 }
380 
381 /* Must be called locked, this will unlock the PET. */
382 static void
lanparm_op_done(ipmi_pet_t * pet,int err)383 lanparm_op_done(ipmi_pet_t *pet, int err)
384 {
385     int           rv;
386 
387     /* Cheap hack, -1 means stop. */
388     if (err == -1)
389 	err = 0;
390 
391     pet->lanparm_err = err;
392     if (pet->lanparm_lock_broken) {
393 	/* Locking is not supported. */
394 	pet_op_done(pet);
395 	goto out;
396     } else {
397 	unsigned char data[1];
398 
399 	if (!pet->lanparm_err && pet->changed_lanparm) {
400 	    /* Don't commit if an error occurred. */
401 	    data[0] = 2; /* commit */
402 	    rv = ipmi_lanparm_set_parm(pet->lanparm, 0, data, 1,
403 				       lanparm_commited, pet);
404 	} else {
405 	    data[0] = 0; /* clear lock */
406 	    rv = ipmi_lanparm_set_parm(pet->lanparm, 0, data, 1,
407 				       lanparm_unlocked, pet);
408 	}
409 	if (rv) {
410 	    ipmi_log(IPMI_LOG_WARNING,
411 		     "pet.c(lanparm_op_done): error clearing lock: 0x%x", rv);
412 	    ipmi_lanparm_destroy(pet->lanparm, NULL, NULL);
413 	    pet->lanparm = NULL;
414 	    pet_op_done(pet);
415 	    goto out;
416 	}
417     }
418     pet_unlock(pet);
419  out:
420     return;
421 }
422 
423 static void lanparm_got_config(ipmi_lanparm_t *lanparm,
424 			       int            err,
425 			       unsigned char  *data,
426 			       unsigned int   data_len,
427 			       void           *cb_data);
428 
429 static int
lanparm_next_config(ipmi_pet_t * pet)430 lanparm_next_config(ipmi_pet_t *pet)
431 {
432     parm_check_t  *check;
433     int           rv;
434 
435     pet->lanparm_check_pos++;
436     if (pet->lanparm_check_pos >= NUM_LANPARM_SETTINGS) {
437 	/* Return non-zero, to end the operation. */
438 	return -1;
439     }
440 
441     check = &(pet->lanparm_check[pet->lanparm_check_pos]);
442 
443     rv = ipmi_lanparm_get_parm(pet->lanparm,
444 			       check->conf_num, check->set,
445 			       0, lanparm_got_config, pet);
446     if (rv) {
447 	ipmi_log(IPMI_LOG_WARNING,
448 		 "pet.c(lanparm_next_config): get err for %d: 0x%x",
449 		 pet->lanparm_check_pos, rv);
450     }
451 
452     return rv;
453 }
454 
455 static void
lanparm_set_config(ipmi_lanparm_t * lanparm,int err,void * cb_data)456 lanparm_set_config(ipmi_lanparm_t *lanparm,
457 		   int            err,
458 		   void           *cb_data)
459 {
460     ipmi_pet_t    *pet = cb_data;
461     int           rv;
462 
463     pet_lock(pet);
464     if (pet->destroyed) {
465 	lanparm_op_done(pet, ECANCELED);
466 	goto out;
467     }
468 
469     if (err) {
470 	ipmi_log(IPMI_LOG_WARNING,
471 		 "pet.c(lanparm_set_config): set failed for %d: 0x%x",
472 		 pet->lanparm_check_pos, err);
473 	lanparm_op_done(pet, err);
474 	goto out;
475     }
476 
477     rv = lanparm_next_config(pet);
478     if (rv) {
479 	lanparm_op_done(pet, rv);
480 	goto out;
481     }
482     pet_unlock(pet);
483  out:
484     return;
485 }
486 
487 static void
lanparm_got_config(ipmi_lanparm_t * lanparm,int err,unsigned char * data,unsigned int data_len,void * cb_data)488 lanparm_got_config(ipmi_lanparm_t *lanparm,
489 		   int            err,
490 		   unsigned char  *data,
491 		   unsigned int   data_len,
492 		   void           *cb_data)
493 {
494     ipmi_pet_t    *pet = cb_data;
495     unsigned char val[22];
496     int           rv;
497     int           pos;
498     parm_check_t  *check;
499     int           check_failed = 0;
500     unsigned int  i;
501 
502     pet_lock(pet);
503     if (pet->destroyed) {
504 	lanparm_op_done(pet, ECANCELED);
505 	goto out;
506     }
507 
508     if (err) {
509 	ipmi_log(IPMI_LOG_WARNING,
510 		 "pet.c(lanparm_got_config): get failed for %d: 0x%x",
511 		 pet->lanparm_check_pos, err);
512 	lanparm_op_done(pet, err);
513 	goto out;
514     }
515 
516     pos = pet->lanparm_check_pos;
517     check = &(pet->lanparm_check[pos]);
518 
519     /* Don't forget to skip the revision number in the length. */
520     if (data_len < (check->data_len+1)) {
521 	ipmi_log(IPMI_LOG_WARNING,
522 		 "pet.c(lanparm_got_config): data length too short for"
523 		 " config %d, was %d, expected %d", check->conf_num,
524 		 data_len, check->data_len);
525 	lanparm_op_done(pet, EINVAL);
526 	goto out;
527     }
528 
529     data++; /* Skip the revision number */
530 
531     /* Check the config item we got and make sure it matches.  If it
532        does not match, send the proper data for it. */
533     for (i=0; i<check->data_len; i++) {
534 	unsigned char checkdata;
535 
536 	checkdata = check->data[i];
537 	if ((data[i] & check->mask[i]) != checkdata) {
538 	    check_failed = 1;
539 	    break;
540 	}
541     }
542 
543     if (check_failed) {
544 	for (i=0; i<check->data_len; i++) {
545 	    unsigned char checkdata;
546 
547 	    checkdata = check->data[i];
548 	    val[i] = (data[i] & ~check->mask[i]) | checkdata;
549 	}
550 	rv = ipmi_lanparm_set_parm(pet->lanparm,
551 				   check->conf_num, val, check->data_len,
552 				   lanparm_set_config, pet);
553 	if (rv) {
554 	    ipmi_log(IPMI_LOG_WARNING,
555 		     "pet.c(lanparm_got_config): sending set: 0x%x",
556 		     rv);
557 	    lanparm_op_done(pet, rv);
558 	    goto out;
559 	}
560 	pet->changed_lanparm = 1;
561     } else {
562 	rv = lanparm_next_config(pet);
563 	if (rv) {
564 	    lanparm_op_done(pet, rv);
565 	    goto out;
566 	}
567     }
568 
569     pet_unlock(pet);
570  out:
571     return;
572 }
573 
574 static void
pef_unlocked(ipmi_pef_t * pef,int err,void * cb_data)575 pef_unlocked(ipmi_pef_t    *pef,
576 	     int           err,
577 	     void          *cb_data)
578 {
579     ipmi_pet_t *pet = cb_data;
580 
581     pet_lock(pet);
582     ipmi_pef_destroy(pet->pef, NULL, NULL);
583     pet->pef = NULL;
584     pet_op_done(pet);
585 }
586 
587 static void
pef_commited(ipmi_pef_t * pef,int err,void * cb_data)588 pef_commited(ipmi_pef_t    *pef,
589 	     int           err,
590 	     void          *cb_data)
591 {
592     ipmi_pet_t    *pet = cb_data;
593     int           rv;
594     unsigned char data[1];
595 
596     pet_lock(pet);
597     if (pet->destroyed) {
598 	ipmi_pef_destroy(pet->pef, NULL, NULL);
599 	pet->pef = NULL;
600 	pet_op_done(pet);
601 	goto out;
602     }
603 
604     /* Ignore the error, committing is optional. */
605 
606     data[0] = 0; /* clear lock */
607     rv = ipmi_pef_set_parm(pet->pef, 0, data, 1,
608 			   pef_unlocked, pet);
609     if (rv) {
610 	ipmi_log(IPMI_LOG_WARNING,
611 		 "pet.c(pef_commited): error clearing lock: 0x%x", rv);
612 	ipmi_pef_destroy(pet->pef, NULL, NULL);
613 	pet->pef = NULL;
614 	pet_op_done(pet);
615 	goto out;
616     }
617     pet_unlock(pet);
618  out:
619     return;
620 }
621 
622 /* Must be called locked, this will unlock the PET. */
623 static void
pef_op_done(ipmi_pet_t * pet,int err)624 pef_op_done(ipmi_pet_t *pet, int err)
625 {
626     int           rv;
627 
628     /* Cheap hack, -1 means stop. */
629     if (err == -1)
630 	err = 0;
631 
632     pet->pef_err = err;
633     if (pet->pef_lock_broken) {
634 	/* Locking is not supported. */
635 	ipmi_pef_destroy(pet->pef, NULL, NULL);
636 	pet->pef = NULL;
637 	pet_op_done(pet);
638 	goto out;
639     } else {
640 	unsigned char data[1];
641 
642 	if (!pet->pef_err && pet->changed_pef) {
643 	    /* Don't commit if an error occurred. */
644 	    data[0] = 2; /* commit */
645 	    rv = ipmi_pef_set_parm(pet->pef, 0, data, 1, pef_commited, pet);
646 	} else {
647 	    data[0] = 0; /* clear lock */
648 	    rv = ipmi_pef_set_parm(pet->pef, 0, data, 1, pef_unlocked, pet);
649 	}
650 	if (rv) {
651 	    ipmi_log(IPMI_LOG_WARNING,
652 		     "pet.c(pef_op_done): error clearing lock: 0x%x", rv);
653 	    pet_op_done(pet);
654 	    ipmi_pef_destroy(pet->pef, NULL, NULL);
655 	    pet->pef = NULL;
656 	    goto out;
657 	}
658     }
659     pet_unlock(pet);
660  out:
661     return;
662 }
663 
664 static void pef_got_config(ipmi_pef_t    *pef,
665 			   int           err,
666 			   unsigned char *data,
667 			   unsigned int  data_len,
668 			   void          *cb_data);
669 
670 static int
pef_next_config(ipmi_pet_t * pet)671 pef_next_config(ipmi_pet_t *pet)
672 {
673     parm_check_t  *check;
674     int           rv;
675 
676     pet->pef_check_pos++;
677     if (pet->pef_check_pos >= NUM_PEF_SETTINGS) {
678 	/* Return non-zero, to end the operation. */
679 	return -1;
680     }
681 
682     check = &(pet->pef_check[pet->pef_check_pos]);
683 
684     rv = ipmi_pef_get_parm(pet->pef, check->conf_num, check->set,
685 			   0, pef_got_config, pet);
686     if (rv) {
687 	ipmi_log(IPMI_LOG_WARNING,
688 		 "pet.c(pef_next_config): PEF get err: 0x%x", rv);
689     }
690 
691     return rv;
692 }
693 
694 static void
pef_set_config(ipmi_pef_t * pef,int err,void * cb_data)695 pef_set_config(ipmi_pef_t    *pef,
696 	       int           err,
697 	       void          *cb_data)
698 {
699     ipmi_pet_t    *pet = cb_data;
700     int           rv;
701 
702     pet_lock(pet);
703     if (pet->destroyed) {
704 	pef_op_done(pet, ECANCELED);
705 	goto out;
706     }
707 
708     if (err) {
709 	ipmi_log(IPMI_LOG_WARNING,
710 		 "pet.c(pef_set_config): PEF set failed for %d: 0x%x",
711 		 pet->pef_check_pos, err);
712 	pef_op_done(pet, err);
713 	goto out;
714     }
715 
716     rv = pef_next_config(pet);
717     if (rv) {
718 	pef_op_done(pet, rv);
719 	goto out;
720     }
721     pet_unlock(pet);
722  out:
723     return;
724 }
725 
726 static void
pef_got_config(ipmi_pef_t * pef,int err,unsigned char * data,unsigned int data_len,void * cb_data)727 pef_got_config(ipmi_pef_t    *pef,
728 	       int           err,
729 	       unsigned char *data,
730 	       unsigned int  data_len,
731 	       void          *cb_data)
732 {
733     ipmi_pet_t    *pet = cb_data;
734     unsigned char val[22];
735     int           rv;
736     int           pos;
737     parm_check_t  *check;
738     int           check_failed = 0;
739     unsigned int  i;
740 
741     pet_lock(pet);
742     if (pet->destroyed) {
743 	pef_op_done(pet, ECANCELED);
744 	goto out;
745     }
746 
747     if (err) {
748 	ipmi_log(IPMI_LOG_WARNING,
749 		 "pet.c(pef_got_control): PEF alloc failed: 0x%x", err);
750 	pef_op_done(pet, err);
751 	goto out;
752     }
753 
754     pos = pet->pef_check_pos;
755     check = &(pet->pef_check[pos]);
756 
757     /* Don't forget to skip the revision number in the length. */
758     if (data_len < check->data_len) {
759 	ipmi_log(IPMI_LOG_WARNING,
760 		 "pet.c(pef_got_cofnfig): PEF data length too short for"
761 		 " config %d, was %d, expected %d", check->conf_num,
762 		 data_len, check->data_len);
763 	pef_op_done(pet, EINVAL);
764 	goto out;
765     }
766 
767     data++; /* Skip the revision number */
768 
769     /* Check the config item we got and make sure it matches.  If it
770        does not match, send the proper data for it. */
771     for (i=0; i<check->data_len; i++) {
772 	if ((data[i] & check->mask[i]) != check->data[i]) {
773 	    check_failed = 1;
774 	    break;
775 	}
776     }
777 
778     if (check_failed) {
779 	for (i=0; i<check->data_len; i++)
780 	    val[i] = (data[i] & ~check->mask[i]) | check->data[i];
781 	rv = ipmi_pef_set_parm(pef, check->conf_num, val, check->data_len,
782 			       pef_set_config, pet);
783 	if (rv) {
784 	    ipmi_log(IPMI_LOG_WARNING,
785 		     "pet.c(pef_got_config): PEF error sending set: 0x%x",
786 		     rv);
787 	    pef_op_done(pet, rv);
788 	    goto out;
789 	}
790 	pet->changed_pef = 1;
791     } else {
792 	rv = pef_next_config(pet);
793 	if (rv) {
794 	    pef_op_done(pet, rv);
795 	    goto out;
796 	}
797     }
798 
799     pet_unlock(pet);
800  out:
801     return;
802 }
803 
804 static void
pef_locked(ipmi_pef_t * pef,int err,void * cb_data)805 pef_locked(ipmi_pef_t *pef,
806 	   int        err,
807 	   void       *cb_data)
808 {
809     ipmi_pet_t    *pet = cb_data;
810     int           rv;
811 
812     pet_lock(pet);
813     if (pet->destroyed) {
814 	pef_op_done(pet, ECANCELED);
815 	goto out;
816     }
817 
818     if (err == 0x80) {
819 	/* No support for locking, just set it so and continue. */
820 	pet->pef_lock_broken = 1;
821     } else if (err) {
822 	ipmi_log(IPMI_LOG_WARNING,
823 		 "pet.c(pef_locked): PEF lock failed: 0x%x", err);
824 	pef_op_done(pet, err);
825 	goto out;
826     }
827 
828     /* Start the configuration process. */
829     rv = ipmi_pef_get_parm(pet->pef, pet->pef_check[0].conf_num,
830 			   pet->pef_check[0].set, 0,
831 			   pef_got_config, pet);
832     if (rv) {
833 	ipmi_log(IPMI_LOG_WARNING,
834 		 "pet.c(pef_locked): PEF control get err: 0x%x", rv);
835 	pef_op_done(pet, rv);
836 	goto out;
837     }
838 
839     pet_unlock(pet);
840  out:
841     return;
842 }
843 
844 static void
pef_alloced(ipmi_pef_t * pef,int err,void * cb_data)845 pef_alloced(ipmi_pef_t *pef, int err, void *cb_data)
846 {
847     ipmi_pet_t    *pet = cb_data;
848     unsigned char data[1];
849     int           rv;
850 
851     pet_lock(pet);
852     if (pet->destroyed) {
853 	pef_op_done(pet, ECANCELED);
854 	goto out;
855     }
856 
857     if (err) {
858 	ipmi_log(IPMI_LOG_WARNING,
859 		 "pet.c(pef_alloced): PEF alloc failed: 0x%x", err);
860 	pef_op_done(pet, err);
861 	goto out;
862     }
863 
864     /* Start the configuration process. */
865     data[0] = 1; /* Attempt to lock */
866     rv = ipmi_pef_set_parm(pet->pef, 0, data, 1,
867 			   pef_locked, pet);
868     if (rv) {
869 	ipmi_log(IPMI_LOG_WARNING,
870 		 "pet.c(pef_alloced): PEF control get err: 0x%x", rv);
871 	pef_op_done(pet, rv);
872 	goto out;
873     }
874 
875     pet_unlock(pet);
876  out:
877     return;
878 }
879 
880 static int
start_pet_setup(ipmi_mc_t * mc,ipmi_pet_t * pet)881 start_pet_setup(ipmi_mc_t  *mc,
882 		ipmi_pet_t *pet)
883 {
884     int  rv = 0;
885 
886     pet_lock(pet);
887 
888     if (pet->in_progress) {
889 	pet_unlock(pet);
890 	return EAGAIN;
891     }
892 
893     pet->pet = pet;
894     pet->pef_lock_broken = 0;
895     pet->pef_err = 0;
896     pet->changed_pef = 0;
897     pet->lanparm_lock_broken = 0;
898     pet->lanparm_err = 0;
899     pet->changed_lanparm = 0;
900 
901     pet->pef_check_pos = 0;
902     pet->in_progress++;
903     pet_get_nolock(pet);
904     rv = ipmi_pef_alloc(mc, pef_alloced, pet, &pet->pef);
905     if (rv) {
906 	pet->in_progress--;
907 	pet_put_nolock(pet);
908 	ipmi_log(IPMI_LOG_WARNING,
909 		 "start_pet_setup: Unable to allocate pef: 0x%x", rv);
910 	goto out;
911     }
912 
913     /* Now that we have the channel, set up the lan parms. */
914     pet->lanparm_check_pos = 0;
915     rv = ipmi_lanparm_alloc(mc, pet->channel, &(pet->lanparm));
916     if (rv) {
917 	ipmi_log(IPMI_LOG_WARNING,
918 		 "start_pet_setup: Unable to allocate lanparm: 0x%x",
919 		 rv);
920     } else {
921 	pet->in_progress++;
922 	pet_get_nolock(pet);
923 	rv = ipmi_lanparm_get_parm(pet->lanparm,
924 				   IPMI_LANPARM_DEST_TYPE,
925 				   pet->lan_dest_sel,
926 				   0,
927 				   lanparm_got_config,
928 				   pet);
929 	if (rv) {
930 	    pet->in_progress--;
931 	    pet_put_nolock(pet);
932 	    ipmi_log(IPMI_LOG_WARNING,
933 		     "start_pet_setup: Unable to get dest type: 0x%x",
934 		     rv);
935 	    ipmi_lanparm_destroy(pet->lanparm, NULL, NULL);
936 	    pet->lanparm = NULL;
937 	}
938     }
939     rv = 0; /* We continue with the PEF run, even if the lanparm fails. */
940 
941  out:
942     pet_unlock(pet);
943     return rv;
944 }
945 
946 int
ipmi_pet_create_mc(ipmi_mc_t * mc,unsigned int channel,struct in_addr ip_addr,unsigned char mac_addr[6],unsigned int eft_sel,unsigned int policy_num,unsigned int apt_sel,unsigned int lan_dest_sel,ipmi_pet_done_cb done,void * cb_data,ipmi_pet_t ** ret_pet)947 ipmi_pet_create_mc(ipmi_mc_t        *mc,
948 		   unsigned int     channel,
949 		   struct in_addr   ip_addr,
950 		   unsigned char    mac_addr[6],
951 		   unsigned int     eft_sel,
952 		   unsigned int     policy_num,
953 		   unsigned int     apt_sel,
954 		   unsigned int     lan_dest_sel,
955 		   ipmi_pet_done_cb done,
956 		   void             *cb_data,
957 		   ipmi_pet_t       **ret_pet)
958 {
959     ipmi_pet_t         *pet;
960     int                rv;
961     os_handler_t       *os_hnd;
962     char               domain_name[IPMI_MC_NAME_LEN];
963     ipmi_domain_t      *domain = ipmi_mc_get_domain(mc);
964     ipmi_domain_attr_t *attr;
965     locked_list_t      *pets;
966 
967     rv = ipmi_domain_register_attribute(domain, IPMI_PET_ATTR_NAME,
968 					pet_attr_init, pet_attr_destroy, NULL,
969 					&attr);
970     if (rv)
971 	return rv;
972     pets = ipmi_domain_attr_get_data(attr);
973 
974     pet = ipmi_mem_alloc(sizeof(*pet));
975     if (!pet) {
976 	ipmi_domain_attr_put(attr);
977 	return ENOMEM;
978     }
979     memset(pet, 0, sizeof(*pet));
980 
981     ipmi_domain_get_name(domain, domain_name, sizeof(domain_name));
982     snprintf(pet->name, sizeof(pet->name), "%s.%d", domain_name,
983 	     ipmi_domain_get_unique_num(domain));
984     pet->refcount = 1;
985     pet->in_list = 1;
986     pet->mc = ipmi_mc_convert_to_id(mc);
987     pet->domain = ipmi_domain_convert_to_id(domain);
988     pet->channel = channel;
989     pet->ip_addr = ip_addr;
990     pet->policy_num = policy_num;
991     pet->eft_sel = eft_sel;
992     pet->apt_sel = apt_sel;
993     pet->lan_dest_sel = lan_dest_sel;
994     pet->done = done;
995     pet->cb_data = cb_data;
996     memcpy(pet->mac_addr, mac_addr, sizeof(pet->mac_addr));
997     pet->in_progress = 0;
998 
999     /* Set up all the data we want in the PEF and LANPARMs
1000        configuration. */
1001     pet->pef_check[0].conf_num = IPMI_PEFPARM_CONTROL;
1002     pet->pef_check[0].data_len = 1;
1003     pet->pef_check[0].data[0] = 1;
1004     pet->pef_check[0].mask[0] = 1;
1005     pet->pef_check[1].conf_num = IPMI_PEFPARM_ACTION_GLOBAL_CONTROL;
1006     pet->pef_check[1].data_len = 1;
1007     pet->pef_check[1].data[0] = 1;
1008     pet->pef_check[1].mask[0] = 1;
1009     pet->pef_check[2].conf_num = IPMI_PEFPARM_EVENT_FILTER_TABLE;
1010     pet->pef_check[2].set = eft_sel;
1011     pet->pef_check[2].data_len = 21;
1012     memset(pet->pef_check[2].data, 0xff, 10);
1013     memset(pet->pef_check[2].data+10, 0, 21-9);
1014     memset(pet->pef_check[2].mask, 0xff, 21);
1015     pet->pef_check[2].data[0] = eft_sel;
1016     pet->pef_check[2].mask[0] = 0x7f;
1017     pet->pef_check[2].data[1] = 0x80;
1018     pet->pef_check[2].mask[1] = 0x80;
1019     pet->pef_check[2].data[2] = 0x01;
1020     pet->pef_check[2].mask[2] = 0x3f;
1021     pet->pef_check[2].data[3] = policy_num;
1022     pet->pef_check[2].mask[3] = 0x0f;
1023     pet->pef_check[2].data[4] = 0;
1024     pet->pef_check[2].data[10] = 0xff;
1025     pet->pef_check[2].data[11] = 0xff;
1026     pet->pef_check[3].conf_num = IPMI_PEFPARM_ALERT_POLICY_TABLE;
1027     pet->pef_check[3].set = apt_sel;
1028     pet->pef_check[3].data_len = 4;
1029     pet->pef_check[3].data[0] = apt_sel;
1030     pet->pef_check[3].mask[0] = 0x7f;
1031     pet->pef_check[3].data[1] = 0x08 | (policy_num << 4);
1032     pet->pef_check[3].mask[1] = 0xff;
1033     pet->pef_check[3].data[2] = (channel << 4) | lan_dest_sel;
1034     pet->pef_check[3].mask[2] = 0xff;
1035     pet->pef_check[3].data[3] = 0;
1036     pet->pef_check[3].mask[3] = 0xff;
1037 
1038     pet->lanparm_check[0].conf_num = IPMI_LANPARM_DEST_TYPE;
1039     pet->lanparm_check[0].set = lan_dest_sel;
1040     pet->lanparm_check[0].data_len = 4;
1041     pet->lanparm_check[0].data[0] = lan_dest_sel;
1042     pet->lanparm_check[0].mask[0] = 0x0f;
1043     pet->lanparm_check[0].data[1] = 0x80;
1044     pet->lanparm_check[0].mask[1] = 0x87;
1045     pet->lanparm_check[0].data[2] = IPMI_LANPARM_DEFAULT_ALERT_RETRY_TIMEOUT;
1046     pet->lanparm_check[0].mask[2] = 0xff;
1047     pet->lanparm_check[0].data[3] = IPMI_LANPARM_DEFAULT_ALERT_RETRIES;
1048     pet->lanparm_check[0].mask[3] = 0x07;
1049     pet->lanparm_check[1].conf_num = IPMI_LANPARM_DEST_ADDR;
1050     pet->lanparm_check[1].set = lan_dest_sel;
1051     pet->lanparm_check[1].data_len = 13;
1052     pet->lanparm_check[1].data[0] = lan_dest_sel;
1053     pet->lanparm_check[1].mask[0] = 0x0f;
1054     pet->lanparm_check[1].data[1] = 0x00;
1055     pet->lanparm_check[1].mask[1] = 0xf0;
1056     pet->lanparm_check[1].data[2] = 0x00;
1057     pet->lanparm_check[1].mask[2] = 0x01;
1058     memset(pet->lanparm_check[1].mask+3, 0xff, 10);
1059     memcpy(pet->lanparm_check[1].data+3, &ip_addr, 4);
1060     memcpy(pet->lanparm_check[1].data+7, mac_addr, 6);
1061 
1062     os_hnd = ipmi_domain_get_os_hnd(domain);
1063     pet->os_hnd = os_hnd;
1064 
1065     /* Start a timer for this PET to periodically check it. */
1066     pet->timer_info = ipmi_mem_alloc(sizeof(*(pet->timer_info)));
1067     if (!pet->timer_info) {
1068 	rv = ENOMEM;
1069 	goto out_err;
1070     }
1071     pet->timer_info->cancelled = 0;
1072     pet->timer_info->os_hnd = os_hnd;
1073     pet->timer_info->pet = pet;
1074     pet->timer_info->running = 0;
1075     pet->timer_info->lock = NULL;
1076     rv = os_hnd->alloc_timer(os_hnd, &pet->timer);
1077     if (rv)
1078 	goto out_err;
1079 
1080     rv = ipmi_create_lock_os_hnd(os_hnd, &pet->timer_info->lock);
1081     if (rv)
1082 	goto out_err;
1083 
1084     if (! locked_list_add(pets, pet, NULL)) {
1085 	rv = ENOMEM;
1086 	goto out_err;
1087     }
1088 
1089     ipmi_domain_attr_put(attr);
1090 
1091     rv = start_pet_setup(mc, pet);
1092     if (rv)
1093 	goto out_err;
1094 
1095     if (ret_pet)
1096 	*ret_pet = pet;
1097 
1098     return 0;
1099 
1100  out_err:
1101     locked_list_remove(pets, pet, NULL);
1102     ipmi_domain_attr_put(attr);
1103     if (pet->timer_info) {
1104 	if (pet->timer) {
1105 	    if (os_hnd->stop_timer(os_hnd, pet->timer) == 0) {
1106 		if (pet->timer_info->lock)
1107 		    ipmi_destroy_lock(pet->timer_info->lock);
1108 		os_hnd->free_timer(os_hnd, pet->timer);
1109 		ipmi_mem_free(pet->timer_info);
1110 	    } else {
1111 		pet->timer_info->cancelled = 1;
1112 	    }
1113 	} else
1114 	    ipmi_mem_free(pet->timer_info);
1115     }
1116     ipmi_mem_free(pet);
1117     return rv;
1118 }
1119 
1120 int
ipmi_pet_create(ipmi_domain_t * domain,unsigned int connection,unsigned int channel,struct in_addr ip_addr,unsigned char mac_addr[6],unsigned int eft_sel,unsigned int policy_num,unsigned int apt_sel,unsigned int lan_dest_sel,ipmi_pet_done_cb done,void * cb_data,ipmi_pet_t ** ret_pet)1121 ipmi_pet_create(ipmi_domain_t    *domain,
1122 		unsigned int     connection,
1123 		unsigned int     channel,
1124 		struct in_addr   ip_addr,
1125 		unsigned char    mac_addr[6],
1126 		unsigned int     eft_sel,
1127 		unsigned int     policy_num,
1128 		unsigned int     apt_sel,
1129 		unsigned int     lan_dest_sel,
1130 		ipmi_pet_done_cb done,
1131 		void             *cb_data,
1132 		ipmi_pet_t       **ret_pet)
1133 {
1134     ipmi_system_interface_addr_t si;
1135     ipmi_mc_t                    *mc;
1136     int                          rv;
1137 
1138     si.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
1139     si.channel = connection;
1140     si.lun = 0;
1141 
1142     mc = i_ipmi_find_mc_by_addr(domain, (ipmi_addr_t *) &si, sizeof(si));
1143     if ((!mc)  && (connection == 0)) {
1144 	/* If the specific connection doesn't exist and the connection
1145 	   is 0, use the BMC channel. */
1146 	si.channel = IPMI_BMC_CHANNEL;
1147 	mc = i_ipmi_find_mc_by_addr(domain, (ipmi_addr_t *) &si,
1148 				    sizeof(si));
1149     }
1150 
1151     if (!mc)
1152 	return EINVAL;
1153 
1154     rv = ipmi_pet_create_mc(mc,
1155 			    channel,
1156 			    ip_addr,
1157 			    mac_addr,
1158 			    eft_sel,
1159 			    policy_num,
1160 			    apt_sel,
1161 			    lan_dest_sel,
1162 			    done,
1163 			    cb_data,
1164 			    ret_pet);
1165     i_ipmi_mc_put(mc);
1166 
1167     return rv;
1168 }
1169 
1170 static void
rescan_pet_mc(ipmi_mc_t * mc,void * cb_data)1171 rescan_pet_mc(ipmi_mc_t *mc, void *cb_data)
1172 {
1173     pet_timer_t *timer_info = cb_data;
1174     ipmi_pet_t  *pet = timer_info->pet;
1175 
1176     timer_info->err = start_pet_setup(mc, pet);
1177 }
1178 
1179 static void
rescan_pet(void * cb_data,os_hnd_timer_id_t * id)1180 rescan_pet(void *cb_data, os_hnd_timer_id_t *id)
1181 {
1182     pet_timer_t    *timer_info = cb_data;
1183     ipmi_pet_t     *pet;
1184     int            rv;
1185     struct timeval timeout;
1186 
1187     ipmi_lock(timer_info->lock);
1188     if (timer_info->cancelled) {
1189 	ipmi_unlock(timer_info->lock);
1190 	timer_info->os_hnd->free_timer(timer_info->os_hnd, id);
1191 	ipmi_destroy_lock(timer_info->lock);
1192 	ipmi_mem_free(timer_info);
1193 	return;
1194     }
1195     pet = timer_info->pet;
1196     pet->timer_info->running = 0;
1197     pet_get(pet);
1198 
1199     timer_info->err = 0;
1200     rv = ipmi_mc_pointer_cb(pet->mc, rescan_pet_mc, timer_info);
1201     if (!rv)
1202 	rv = timer_info->err;
1203 
1204     if (rv) {
1205 	os_handler_t *os_hnd = timer_info->os_hnd;
1206 	/* Got an error, just restart the timer */
1207 	timeout.tv_sec = PET_TIMEOUT_SEC;
1208 	timeout.tv_usec = 0;
1209 	os_hnd->start_timer(os_hnd, pet->timer, &timeout, rescan_pet,
1210 			    pet->timer_info);
1211 	pet->timer_info->running = 1;
1212     }
1213 
1214     ipmi_unlock(timer_info->lock);
1215 }
1216 
1217 int
ipmi_pet_destroy(ipmi_pet_t * pet,ipmi_pet_done_cb done,void * cb_data)1218 ipmi_pet_destroy(ipmi_pet_t       *pet,
1219 		 ipmi_pet_done_cb done,
1220 		 void             *cb_data)
1221 
1222 {
1223     pet_lock(pet);
1224     if (pet->in_list) {
1225 	ipmi_domain_attr_t *attr;
1226 	locked_list_t      *pets;
1227 	int                rv;
1228 
1229 	pet->in_list = 0;
1230 	rv = ipmi_domain_id_find_attribute(pet->domain,
1231 					   IPMI_PET_ATTR_NAME, &attr);
1232 	if (!rv) {
1233 	    pet_unlock(pet);
1234 
1235 	    pets = ipmi_domain_attr_get_data(attr);
1236 
1237 	    locked_list_remove(pets, pet, NULL);
1238 	    ipmi_domain_attr_put(attr);
1239 	    pet_lock(pet);
1240 	}
1241     }
1242 
1243     pet->destroyed = 1;
1244     pet->destroy_done = done;
1245     pet->destroy_cb_data = cb_data;
1246     pet_unlock(pet);
1247 
1248     pet_put(pet);
1249     return 0;
1250 }
1251 
1252 int
ipmi_pet_get_name(ipmi_pet_t * pet,char * name,int length)1253 ipmi_pet_get_name(ipmi_pet_t *pet, char *name, int length)
1254 {
1255     int  slen;
1256 
1257     if (length <= 0)
1258 	return 0;
1259 
1260     /* Never changes, no lock needed. */
1261     slen = strlen(pet->name);
1262     if (slen == 0) {
1263 	if (name)
1264 	    *name = '\0';
1265 	goto out;
1266     }
1267 
1268     if (name) {
1269 	memcpy(name, pet->name, slen);
1270 	name[slen] = '\0';
1271     }
1272  out:
1273     return slen;
1274 }
1275 
1276 typedef struct iterate_pets_info_s
1277 {
1278     ipmi_pet_ptr_cb handler;
1279     void            *cb_data;
1280 } iterate_pets_info_t;
1281 
1282 static int
pets_handler(void * cb_data,void * item1,void * item2)1283 pets_handler(void *cb_data, void *item1, void *item2)
1284 {
1285     iterate_pets_info_t *info = cb_data;
1286     info->handler(item1, info->cb_data);
1287     pet_put(item1);
1288     return LOCKED_LIST_ITER_CONTINUE;
1289 }
1290 
1291 static int
pets_prefunc(void * cb_data,void * item1,void * item2)1292 pets_prefunc(void *cb_data, void *item1, void *item2)
1293 {
1294     pet_get(item1);
1295     return LOCKED_LIST_ITER_CONTINUE;
1296 }
1297 
1298 void
ipmi_pet_iterate_pets(ipmi_domain_t * domain,ipmi_pet_ptr_cb handler,void * cb_data)1299 ipmi_pet_iterate_pets(ipmi_domain_t   *domain,
1300 		      ipmi_pet_ptr_cb handler,
1301 		      void            *cb_data)
1302 {
1303     iterate_pets_info_t info;
1304     ipmi_domain_attr_t  *attr;
1305     locked_list_t       *pets;
1306     int                 rv;
1307 
1308     rv = ipmi_domain_find_attribute(domain, IPMI_PET_ATTR_NAME,
1309 				    &attr);
1310     if (rv)
1311 	return;
1312     pets = ipmi_domain_attr_get_data(attr);
1313 
1314     info.handler = handler;
1315     info.cb_data = cb_data;
1316     locked_list_iterate_prefunc(pets, pets_prefunc, pets_handler, &info);
1317     ipmi_domain_attr_put(attr);
1318 }
1319 
1320 ipmi_mcid_t
ipmi_pet_get_mc_id(ipmi_pet_t * pet)1321 ipmi_pet_get_mc_id(ipmi_pet_t *pet)
1322 {
1323     return pet->mc;
1324 }
1325 
1326 unsigned int
ipmi_pet_get_channel(ipmi_pet_t * pet)1327 ipmi_pet_get_channel(ipmi_pet_t *pet)
1328 {
1329     return pet->channel;
1330 }
1331 
1332 struct in_addr *
ipmi_pet_get_ip_addr(ipmi_pet_t * pet,struct in_addr * ip_addr)1333 ipmi_pet_get_ip_addr(ipmi_pet_t *pet, struct in_addr *ip_addr)
1334 {
1335     memcpy(ip_addr, &pet->ip_addr, sizeof(*ip_addr));
1336     return ip_addr;
1337 }
1338 
1339 unsigned char *
ipmi_pet_get_mac_addr(ipmi_pet_t * pet,unsigned char mac_addr[6])1340 ipmi_pet_get_mac_addr(ipmi_pet_t *pet, unsigned char mac_addr[6])
1341 {
1342     memcpy(mac_addr, pet->mac_addr, 6);
1343     return mac_addr;
1344 }
1345 
1346 unsigned int
ipmi_pet_get_eft_sel(ipmi_pet_t * pet)1347 ipmi_pet_get_eft_sel(ipmi_pet_t *pet)
1348 {
1349     return pet->eft_sel;
1350 }
1351 
1352 unsigned int
ipmi_pet_get_policy_num(ipmi_pet_t * pet)1353 ipmi_pet_get_policy_num(ipmi_pet_t *pet)
1354 {
1355     return pet->policy_num;
1356 }
1357 
1358 unsigned int
ipmi_pet_get_apt_sel(ipmi_pet_t * pet)1359 ipmi_pet_get_apt_sel(ipmi_pet_t *pet)
1360 {
1361     return pet->apt_sel;
1362 }
1363 
1364 unsigned int
ipmi_pet_get_lan_dest_sel(ipmi_pet_t * pet)1365 ipmi_pet_get_lan_dest_sel(ipmi_pet_t *pet)
1366 {
1367     return pet->lan_dest_sel;
1368 }
1369