mrpd: comment cleanup
[profile/ivi/OpenAVB.git] / daemons / mrpd / msrp.c
1 /****************************************************************************
2   Copyright (c) 2012, Intel Corporation
3   All rights reserved.
4
5   Redistribution and use in source and binary forms, with or without
6   modification, are permitted provided that the following conditions are met:
7
8    1. Redistributions of source code must retain the above copyright notice,
9       this list of conditions and the following disclaimer.
10
11    2. Redistributions in binary form must reproduce the above copyright
12       notice, this list of conditions and the following disclaimer in the
13       documentation and/or other materials provided with the distribution.
14
15    3. Neither the name of the Intel Corporation nor the names of its
16       contributors may be used to endorse or promote products derived from
17       this software without specific prior written permission.
18
19   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29   POSSIBILITY OF SUCH DAMAGE.
30
31 ******************************************************************************/
32 /*
33  * MSRP protocol (part of 802.1Q-2011)
34  */
35
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <stddef.h>
39 #include <string.h>
40
41 #include "parse.h"
42 #include "mrpd.h"
43 #include "mrp.h"
44 #include "msrp.h"
45 #include "mmrp.h"
46
47 int msrp_txpdu(void);
48 int msrp_send_notifications(struct msrp_attribute *attrib, int notify);
49
50 unsigned char MSRP_ADDR[] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x0E };
51
52 extern unsigned char STATION_ADDR[];
53
54 /* global variables */
55 SOCKET msrp_socket;
56 struct msrp_database *MSRP_db;
57
58 struct msrp_attribute *msrp_lookup(struct msrp_attribute *rattrib)
59 {
60         struct msrp_attribute *attrib;
61         int mac_eq;
62
63         attrib = MSRP_db->attrib_list;
64         while (NULL != attrib) {
65                 if (rattrib->type == attrib->type) {
66                         if (MSRP_DOMAIN_TYPE == attrib->type) {
67                                 mac_eq = memcmp(&(attrib->attribute.domain),
68                                                 &(rattrib->attribute.domain),
69                                                 sizeof(msrpdu_domain_t));
70                                 if (0 == mac_eq)
71                                         return attrib;
72                         } else {
73                                 /* compare on the stream ID */
74                                 mac_eq =
75                                     memcmp(attrib->attribute.talk_listen.
76                                            StreamID,
77                                            rattrib->attribute.talk_listen.
78                                            StreamID, 8);
79                                 if (0 == mac_eq)
80                                         return attrib;
81                         }
82                 }
83                 attrib = attrib->next;
84         }
85         return NULL;
86 }
87
88 int msrp_add(struct msrp_attribute *rattrib)
89 {
90         struct msrp_attribute *attrib;
91         struct msrp_attribute *attrib_tail;
92         int mac_eq;
93
94         /* XXX do a lookup first to guarantee uniqueness? */
95
96         attrib_tail = attrib = MSRP_db->attrib_list;
97
98         while (NULL != attrib) {
99                 /* sort list into types, then sorted in order within types */
100                 if (rattrib->type == attrib->type) {
101                         if (MSRP_DOMAIN_TYPE == attrib->type) {
102                                 mac_eq = memcmp(&(attrib->attribute.domain),
103                                                 &(rattrib->attribute.domain),
104                                                 sizeof(msrpdu_domain_t));
105
106                                 if (mac_eq < 0) {
107                                         /* possible tail insertion ... */
108
109                                         /*
110                                          * see if there is a another of the same following
111                                          * not likely since valid values are only 0 and 1
112                                          */
113                                         if (NULL != attrib->next) {
114                                                 if (attrib->type ==
115                                                     attrib->next->type) {
116                                                         attrib = attrib->next;
117                                                         continue;
118                                                 }
119                                         }
120
121                                         rattrib->next = attrib->next;
122                                         rattrib->prev = attrib;
123                                         attrib->next = rattrib;
124                                         return 0;
125
126                                 } else {
127                                         /* head insertion ... */
128                                         rattrib->next = attrib;
129                                         rattrib->prev = attrib->prev;
130                                         attrib->prev = rattrib;
131                                         if (NULL != rattrib->prev)
132                                                 rattrib->prev->next = rattrib;
133                                         else
134                                                 MSRP_db->attrib_list = rattrib;
135
136                                         return 0;
137                                 }
138                         } else {
139                                 mac_eq =
140                                     memcmp(attrib->attribute.talk_listen.
141                                            StreamID,
142                                            rattrib->attribute.talk_listen.
143                                            StreamID, 8);
144
145                                 if (mac_eq < 0) {
146                                         /* possible tail insertion ... */
147
148                                         if (NULL != attrib->next) {
149                                                 if (attrib->type ==
150                                                     attrib->next->type) {
151                                                         attrib = attrib->next;
152                                                         continue;
153                                                 }
154                                         }
155
156                                         rattrib->next = attrib->next;
157                                         rattrib->prev = attrib;
158                                         attrib->next = rattrib;
159                                         return 0;
160
161                                 } else {
162                                         /* head insertion ... */
163                                         rattrib->next = attrib;
164                                         rattrib->prev = attrib->prev;
165                                         attrib->prev = rattrib;
166                                         if (NULL != rattrib->prev)
167                                                 rattrib->prev->next = rattrib;
168                                         else
169                                                 MSRP_db->attrib_list = rattrib;
170
171                                         return 0;
172                                 }
173                         }
174                 }
175                 attrib_tail = attrib;
176                 attrib = attrib->next;
177         }
178
179         /* if we are here we didn't need to stitch in a a sorted entry
180          * so append it onto the tail (if it exists)
181          */
182
183         if (NULL == attrib_tail) {
184                 rattrib->next = NULL;
185                 rattrib->prev = NULL;
186                 MSRP_db->attrib_list = rattrib;
187         } else {
188                 rattrib->next = NULL;
189                 rattrib->prev = attrib_tail;
190                 attrib_tail->next = rattrib;
191         }
192
193         return 0;
194 }
195
196 int msrp_merge(struct msrp_attribute *rattrib)
197 {
198         struct msrp_attribute *attrib;
199
200         attrib = msrp_lookup(rattrib);
201
202         if (NULL == attrib)
203                 return -1;      /* shouldn't happen */
204
205         /* we always update the last mac address state for diagnostics */
206         memcpy(attrib->registrar.macaddr, rattrib->registrar.macaddr, 6);
207
208         /* some attribute types carry updated fault condition information
209          * from the bridges indicating either insufficient bandwidth or
210          * excessive latency between the talker and listener. We merge
211          * these status conditions with the existing attribute without
212          * necessarily changing the MRP state (we let the FSM functions
213          * handle these)
214          */
215         switch (attrib->type) {
216         case MSRP_TALKER_ADV_TYPE:
217         case MSRP_TALKER_FAILED_TYPE:
218                 attrib->attribute.talk_listen.FailureInformation.FailureCode =
219                     rattrib->attribute.talk_listen.FailureInformation.
220                     FailureCode;
221                 memcpy(attrib->attribute.talk_listen.FailureInformation.
222                        BridgeID,
223                        rattrib->attribute.talk_listen.FailureInformation.
224                        BridgeID, 8);
225                 attrib->attribute.talk_listen.AccumulatedLatency =
226                     rattrib->attribute.talk_listen.AccumulatedLatency;
227                 break;
228         case MSRP_LISTENER_TYPE:
229                 if (attrib->substate != rattrib->substate) {
230                         attrib->substate = rattrib->substate;
231                         attrib->registrar.mrp_state = MRP_MT_STATE;     /* ugly - force a notify */
232                 }
233                 break;
234         case MSRP_DOMAIN_TYPE:
235                 /* doesn't/shouldn't happen */
236                 break;
237         default:
238                 break;
239         }
240         return 0;
241 }
242
243 int msrp_event(int event, struct msrp_attribute *rattrib)
244 {
245         struct msrp_attribute *attrib;
246         int rc;
247
248         switch (event) {
249         case MRP_EVENT_LVATIMER:
250                 mrp_jointimer_stop(&(MSRP_db->mrp_db));
251                 /* update state */
252                 attrib = MSRP_db->attrib_list;
253
254                 while (NULL != attrib) {
255                         mrp_applicant_fsm(&(attrib->applicant), MRP_EVENT_TXLA);
256                         mrp_registrar_fsm(&(attrib->registrar),
257                                           &(MSRP_db->mrp_db), MRP_EVENT_TXLA);
258                         attrib = attrib->next;
259                 }
260
261                 mrp_lvatimer_fsm(&(MSRP_db->mrp_db), MRP_EVENT_LVATIMER);
262
263                 msrp_txpdu();
264                 break;
265         case MRP_EVENT_RLA:
266                 mrp_jointimer_stop(&(MSRP_db->mrp_db));
267                 /* update state */
268                 attrib = MSRP_db->attrib_list;
269
270                 while (NULL != attrib) {
271                         mrp_applicant_fsm(&(attrib->applicant), MRP_EVENT_RLA);
272                         mrp_registrar_fsm(&(attrib->registrar),
273                                           &(MSRP_db->mrp_db), MRP_EVENT_RLA);
274                         attrib = attrib->next;
275                 }
276
277                 mrp_lvatimer_fsm(&(MSRP_db->mrp_db), MRP_EVENT_RLA);
278
279                 break;
280         case MRP_EVENT_TX:
281                 mrp_jointimer_stop(&(MSRP_db->mrp_db));
282                 attrib = MSRP_db->attrib_list;
283
284                 while (NULL != attrib) {
285                         mrp_applicant_fsm(&(attrib->applicant), MRP_EVENT_TX);
286                         attrib = attrib->next;
287                 }
288
289                 mrp_lvatimer_fsm(&(MSRP_db->mrp_db), MRP_EVENT_TX);
290
291                 msrp_txpdu();
292                 break;
293         case MRP_EVENT_LVTIMER:
294                 mrp_lvtimer_stop(&(MSRP_db->mrp_db));
295                 attrib = MSRP_db->attrib_list;
296
297                 while (NULL != attrib) {
298                         mrp_registrar_fsm(&(attrib->registrar),
299                                           &(MSRP_db->mrp_db),
300                                           MRP_EVENT_LVTIMER);
301
302                         attrib = attrib->next;
303                 }
304                 break;
305         case MRP_EVENT_PERIODIC:
306                 attrib = MSRP_db->attrib_list;
307
308                 while (NULL != attrib) {
309                         mrp_applicant_fsm(&(attrib->applicant),
310                                           MRP_EVENT_PERIODIC);
311                         attrib = attrib->next;
312                 }
313                 break;
314         case MRP_EVENT_NEW:
315         case MRP_EVENT_JOIN:
316         case MRP_EVENT_RNEW:
317         case MRP_EVENT_RJOININ:
318         case MRP_EVENT_RJOINMT:
319         case MRP_EVENT_LV:
320         case MRP_EVENT_RIN:
321         case MRP_EVENT_RMT:
322         case MRP_EVENT_RLV:
323                 mrp_jointimer_start(&(MSRP_db->mrp_db));
324                 if (NULL == rattrib)
325                         return -1;      /* XXX internal fault */
326
327                 /* update state */
328                 attrib = msrp_lookup(rattrib);
329
330                 if (NULL == attrib) {
331                         msrp_add(rattrib);
332                         attrib = rattrib;
333                 } else {
334                         msrp_merge(rattrib);
335                         free(rattrib);
336                 }
337
338                 mrp_applicant_fsm(&(attrib->applicant), event);
339
340                 /* remap local requests into registrar events */
341                 switch (event) {
342                 case MRP_EVENT_NEW:
343                         mrp_registrar_fsm(&(attrib->registrar),
344                                           &(MSRP_db->mrp_db), MRP_EVENT_RNEW);
345                         break;
346                 case MRP_EVENT_JOIN:
347                         if (MRP_IN_STATE == attrib->registrar.mrp_state)
348                                 mrp_registrar_fsm(&(attrib->registrar),
349                                                   &(MSRP_db->mrp_db),
350                                                   MRP_EVENT_RJOININ);
351                         else
352                                 mrp_registrar_fsm(&(attrib->registrar),
353                                                   &(MSRP_db->mrp_db),
354                                                   MRP_EVENT_RJOINMT);
355                         break;
356                 case MRP_EVENT_LV:
357                         mrp_registrar_fsm(&(attrib->registrar),
358                                           &(MSRP_db->mrp_db), MRP_EVENT_RLV);
359                         break;
360                 default:
361                         rc = mrp_registrar_fsm(&(attrib->registrar),
362                                                &(MSRP_db->mrp_db), event);
363                         if (-1 == rc) {
364                                 printf
365                                     ("MSRP registrar error on attrib->type = %d\n",
366                                      attrib->type);
367                         }
368                         break;
369                 }
370                 break;
371         default:
372                 break;
373         }
374
375         /*
376          * XXX should honor the MSRP_db->mrp_db.registration and
377          * MSRP_db->mrp_db.participant controls
378          */
379
380         /* generate local notifications */
381         attrib = MSRP_db->attrib_list;
382
383         while (NULL != attrib) {
384                 if (MRP_NOTIFY_NONE != attrib->registrar.notify) {
385                         msrp_send_notifications(attrib,
386                                                 attrib->registrar.notify);
387                         attrib->registrar.notify = MRP_NOTIFY_NONE;
388                 }
389                 attrib = attrib->next;
390         }
391
392         return 0;
393 }
394
395 struct msrp_attribute *msrp_alloc()
396 {
397         struct msrp_attribute *attrib;
398
399         attrib = malloc(sizeof(struct msrp_attribute));
400         if (NULL == attrib)
401                 return NULL;
402
403         memset(attrib, 0, sizeof(struct msrp_attribute));
404
405         attrib->applicant.mrp_state = MRP_VO_STATE;
406         attrib->applicant.tx = 0;
407         attrib->applicant.sndmsg = MRP_SND_NULL;
408         attrib->applicant.encode = MRP_ENCODE_OPTIONAL;
409
410         attrib->registrar.mrp_state = MRP_MT_STATE;
411         attrib->registrar.notify = MRP_NOTIFY_NONE;
412
413         return attrib;
414 }
415
416 void msrp_increment_streamid(uint8_t * streamid)
417 {
418
419         int i;
420
421         i = 7;
422         while (i > 0) {
423                 if (255 != streamid[i]) {
424                         streamid[i]++;
425                         return;
426                 }
427                 streamid[i] = 0;
428                 i--;
429         }
430         return;
431 }
432
433 int msrp_recv_msg()
434 {
435         char *msgbuf;
436         int bytes = 0;
437         eth_hdr_t *eth;
438         mrpdu_t *mrpdu;
439         mrpdu_message_t *mrpdu_msg;
440         unsigned char *mrpdu_msg_ptr;
441         unsigned char *mrpdu_msg_eof;
442         mrpdu_vectorattrib_t *mrpdu_vectorptr;
443         uint16_t numvalues;
444         uint16_t numvalues_processed;
445         int numvectorbytes;
446         uint8_t vect_3pack;
447         uint8_t vect_4pack;
448         int vectidx;
449         int vectevt[4];
450         int vectevt_idx;
451         uint8_t srclassID_firstval;
452         uint8_t srclassprio_firstval;
453         uint16_t srclassvid_firstval;
454         uint8_t streamid_firstval[8];
455         uint8_t destmac_firstval[6];
456         struct msrp_attribute *attrib;
457         int endmarks;
458         int *listener_vectevt = NULL;
459         int listener_vectevt_sz = 0;
460         int listener_vectevt_idx;
461         int listener_endbyte;
462
463         bytes = mrpd_recvmsgbuf(msrp_socket, &msgbuf);
464         if (bytes <= 0)
465                 goto out;
466         if ((unsigned int)bytes < (sizeof(eth_hdr_t) + sizeof(mrpdu_t) +
467                                    sizeof(mrpdu_message_t)))
468                 goto out;
469
470         eth = (eth_hdr_t *) msgbuf;
471
472         /* note that MSRP frames should always arrive untagged (no vlan) */
473         if (MSRP_ETYPE != ntohs(eth->typelen)) {
474                 goto out;
475         }
476         /* XXX check dest mac address too? */
477
478         mrpdu = (mrpdu_t *) (msgbuf + sizeof(struct eth_hdr));
479
480         /*
481          * ProtocolVersion handling - a receiver must process received frames with a lesser
482          * protocol version consistent with the older protocol processing requirements (e.g. a V2
483          * agent receives a V1 message, the V1 message should be parsed with V1 rules).
484          *
485          * However - if an agent receives a NEWER protocol, the agent should still attempt
486          * to parse the frame. If the agent finds an AttributeType not recognized
487          * the agent discards the current message including any associated trailing vectors
488          * up to the end-mark, and resumes with the next message or until the end of the PDU
489          * is reached.
490          *
491          * If a VectorAttribute is found with an unknown Event for the Type, the specific
492          * VectorAttrute is discarded and processing continues with the next VectorAttribute.
493          */
494
495         if (MSRP_PROT_VER != mrpdu->ProtocolVersion) {  /* XXX should accept ... */
496                 goto out;
497         }
498         mrpdu_msg_ptr = MRPD_GET_MRPDU_MESSAGE_LIST(mrpdu);
499
500         mrpdu_msg_eof = (unsigned char *)mrpdu_msg_ptr;
501         mrpdu_msg_eof += bytes;
502         mrpdu_msg_eof -= sizeof(eth_hdr_t);
503         mrpdu_msg_eof -= MRPD_OFFSETOF_MRPD_GET_MRPDU_MESSAGE_LIST;
504
505         endmarks = 0;
506
507         while (mrpdu_msg_ptr < (mrpdu_msg_eof - 2)) {
508                 mrpdu_msg = (mrpdu_message_t *) mrpdu_msg_ptr;
509                 if ((mrpdu_msg->AttributeType == 0) &&
510                     (mrpdu_msg->AttributeLength == 0)) {
511                         mrpdu_msg_ptr += 2;
512                         endmarks++;
513                         if (endmarks < 2)
514                                 continue;       /* end-mark of message-list */
515                         else {
516                                 break;  /* two endmarks - end of message list */
517                         }
518                 }
519
520                 endmarks = 0;
521                 switch (mrpdu_msg->AttributeType) {
522                 case MSRP_DOMAIN_TYPE:
523                         if (mrpdu_msg->AttributeLength != 4) {
524                                 /* we can seek for an endmark to recover .. but this version
525                                  * dumps the entire packet as malformed
526                                  */
527                                 goto out;
528                         }
529
530                         mrpdu_vectorptr =
531                             (mrpdu_vectorattrib_t *)&(mrpdu_msg->Data[2]);
532                         mrpdu_msg_ptr = (uint8_t *) mrpdu_vectorptr;
533                         while (!((mrpdu_msg_ptr[0] == 0)
534                                  && (mrpdu_msg_ptr[1] == 0))) {
535                                 numvalues =
536                                     MRPDU_VECT_NUMVALUES(ntohs
537                                                          (mrpdu_vectorptr->
538                                                           VectorHeader));
539
540                                 if (0 == numvalues) {
541                                         /* skip this null attribute ... some switches generate these ... */
542                                         /* 2 byte numvalues + 4 byte FirstValue + (0) vector bytes */
543                                         mrpdu_msg_ptr =
544                                             (uint8_t *) mrpdu_vectorptr;
545                                         mrpdu_msg_ptr += 6;
546
547                                         mrpdu_vectorptr =
548                                             (mrpdu_vectorattrib_t *)
549                                             mrpdu_msg_ptr;
550                                         continue;
551                                 }
552                                 if ((mrpdu_vectorptr->FirstValue_VectorEvents +
553                                      numvalues / 3) >= mrpdu_msg_eof) {
554                                         /* Malformed - runs off the end of the pdu */
555                                         goto out;
556                                 }
557                                 srclassID_firstval =
558                                     mrpdu_vectorptr->FirstValue_VectorEvents[0];
559                                 srclassprio_firstval =
560                                     mrpdu_vectorptr->FirstValue_VectorEvents[1];
561                                 srclassvid_firstval = ((uint16_t)
562                                                        mrpdu_vectorptr->
563                                                        FirstValue_VectorEvents
564                                                        [2]) << 8 |
565                                     mrpdu_vectorptr->FirstValue_VectorEvents[3];
566
567                                 /* if not an even multiple ... */
568                                 if (numvalues != ((numvalues / 3) * 3))
569                                         numvectorbytes = (numvalues / 3) + 1;
570                                 else
571                                         numvectorbytes = (numvalues / 3);
572
573                                 for (vectidx = 4;
574                                      vectidx <= (numvectorbytes + 4);
575                                      vectidx++) {
576                                         vect_3pack =
577                                             mrpdu_vectorptr->
578                                             FirstValue_VectorEvents[vectidx];
579                                         vectevt[0] = vect_3pack / 36;
580                                         vectevt[1] =
581                                             (vect_3pack - vectevt[0] * 36) / 6;
582                                         vectevt[2] =
583                                             vect_3pack - (36 * vectevt[0]) -
584                                             (6 * vectevt[1]);
585
586                                         numvalues_processed =
587                                             (numvalues > 3 ? 3 : numvalues);
588
589                                         for (vectevt_idx = 0;
590                                              vectevt_idx < numvalues_processed;
591                                              vectevt_idx++) {
592
593                                                 attrib = msrp_alloc();
594                                                 if (NULL == attrib)
595                                                         goto out;       /* oops - internal error */
596
597                                                 attrib->type = MSRP_DOMAIN_TYPE;
598                                                 attrib->attribute.domain.
599                                                     SRclassID =
600                                                     srclassID_firstval;
601                                                 attrib->attribute.domain.
602                                                     SRclassPriority =
603                                                     srclassprio_firstval;
604                                                 attrib->attribute.domain.
605                                                     SRclassVID =
606                                                     srclassvid_firstval;
607
608                                                 srclassID_firstval++;
609                                                 srclassprio_firstval++;
610
611                                                 memcpy(attrib->registrar.
612                                                        macaddr, eth->srcaddr,
613                                                        6);
614
615                                                 switch (vectevt[vectevt_idx]) {
616                                                 case MRPDU_NEW:
617                                                         msrp_event
618                                                             (MRP_EVENT_RNEW,
619                                                              attrib);
620                                                         break;
621                                                 case MRPDU_JOININ:
622                                                         msrp_event
623                                                             (MRP_EVENT_RJOININ,
624                                                              attrib);
625                                                         break;
626                                                 case MRPDU_IN:
627                                                         msrp_event
628                                                             (MRP_EVENT_RIN,
629                                                              attrib);
630                                                         break;
631                                                 case MRPDU_JOINMT:
632                                                         msrp_event
633                                                             (MRP_EVENT_RJOINMT,
634                                                              attrib);
635                                                         break;
636                                                 case MRPDU_MT:
637                                                         msrp_event
638                                                             (MRP_EVENT_RMT,
639                                                              attrib);
640                                                         break;
641                                                 case MRPDU_LV:
642                                                         msrp_event
643                                                             (MRP_EVENT_RLV,
644                                                              attrib);
645                                                         break;
646                                                 default:
647                                                         free(attrib);
648                                                         break;
649                                                 }
650                                         }
651                                         numvalues -= numvalues_processed;
652                                 }
653
654                                 if (MRPDU_VECT_LVA
655                                     (ntohs(mrpdu_vectorptr->VectorHeader)))
656                                         msrp_event(MRP_EVENT_RLA, NULL);
657
658                                 /* 2 byte numvalues + 4 byte FirstValue + (n) vector bytes */
659                                 mrpdu_msg_ptr = (uint8_t *) mrpdu_vectorptr;
660                                 mrpdu_msg_ptr += 6 + numvectorbytes;
661
662                                 mrpdu_vectorptr =
663                                     (mrpdu_vectorattrib_t *) mrpdu_msg_ptr;
664                         }
665                         break;
666                 case MSRP_LISTENER_TYPE:
667                         if (mrpdu_msg->AttributeLength != 8) {
668                                 /* we can seek for an endmark to recover .. but this version
669                                  * dumps the entire packet as malformed
670                                  */
671                                 goto out;
672                         }
673
674                         /* MSRP uses AttributeListLength ...  */
675                         mrpdu_vectorptr =
676                             (mrpdu_vectorattrib_t *)&(mrpdu_msg->Data[2]);
677                         mrpdu_msg_ptr = (uint8_t *) mrpdu_vectorptr;
678
679                         while (!((mrpdu_msg_ptr[0] == 0)
680                                  && (mrpdu_msg_ptr[1] == 0))) {
681                                 numvalues =
682                                     MRPDU_VECT_NUMVALUES(ntohs
683                                                          (mrpdu_vectorptr->
684                                                           VectorHeader));
685
686                                 if (0 == numvalues) {
687                                         /* 2 byte numvalues + 8 byte FirstValue + (0) vector bytes */
688                                         mrpdu_msg_ptr =
689                                             (uint8_t *) mrpdu_vectorptr;
690                                         mrpdu_msg_ptr += 10;
691
692                                         mrpdu_vectorptr =
693                                             (mrpdu_vectorattrib_t *)
694                                             mrpdu_msg_ptr;
695                                         /* Malformed - cant tell how long the trailing vectors are */
696                                         continue;
697                                 }
698                                 if ((mrpdu_vectorptr->FirstValue_VectorEvents +
699                                      numvalues / 3 + numvalues / 4) >=
700                                     mrpdu_msg_eof) {
701                                         /* Malformed - runs off the end of the pdu */
702                                         goto out;
703                                 }
704                                 memcpy(streamid_firstval,
705                                        &
706                                        (mrpdu_vectorptr->FirstValue_VectorEvents
707                                         [0]), 8);
708
709                                 /*
710                                  * parse the 4-packed events first to figure out the substates, then
711                                  * insert them as we parse the 3-packed events for the MRP state machines
712                                  */
713
714                                 /* if not an even multiple ... */
715                                 if (numvalues != ((numvalues / 4) * 4))
716                                         numvectorbytes = (numvalues / 4) + 1;
717                                 else
718                                         numvectorbytes = (numvalues / 4);
719
720                                 if (numvalues != ((numvalues / 3) * 3))
721                                         vectidx = 8 + (numvalues / 3) + 1;
722                                 else
723                                         vectidx = 8 + (numvalues / 3);
724
725                                 listener_endbyte = vectidx + numvectorbytes;
726
727                                 if (&
728                                     (mrpdu_vectorptr->FirstValue_VectorEvents
729                                      [listener_endbyte]) >= mrpdu_msg_eof)
730                                         goto out;
731
732                                 if (NULL == listener_vectevt) {
733                                         listener_vectevt_sz = 64;;
734                                         listener_vectevt =
735                                             (int *)malloc(listener_vectevt_sz *
736                                                           sizeof(int));
737                                         if (NULL == listener_vectevt)
738                                                 goto out;
739                                 }
740
741                                 listener_vectevt_idx = 0;
742
743                                 for (; vectidx < listener_endbyte; vectidx++) {
744                                         vect_4pack =
745                                             mrpdu_vectorptr->
746                                             FirstValue_VectorEvents[vectidx];
747
748                                         vectevt[3] =
749                                             vect_4pack -
750                                             ((vect_4pack >> 2) << 2);
751                                         vect_4pack = vect_4pack >> 2;
752                                         vectevt[2] =
753                                             vect_4pack -
754                                             ((vect_4pack >> 2) << 2);
755                                         vect_4pack = vect_4pack >> 2;
756                                         vectevt[1] =
757                                             vect_4pack -
758                                             ((vect_4pack >> 2) << 2);
759                                         vect_4pack = vect_4pack >> 2;
760                                         vectevt[0] =
761                                             vect_4pack -
762                                             ((vect_4pack >> 2) << 2);
763                                         vect_4pack = vect_4pack >> 2;
764
765                                         numvalues_processed =
766                                             (numvalues > 4 ? 4 : numvalues);
767
768                                         for (vectevt_idx = 0;
769                                              vectevt_idx < numvalues_processed;
770                                              vectevt_idx++) {
771                                                 if (listener_vectevt_idx ==
772                                                     listener_vectevt_sz) {
773                                                         listener_vectevt =
774                                                             realloc
775                                                             (listener_vectevt,
776                                                              (listener_vectevt_sz
777                                                               +
778                                                               64) *
779                                                              sizeof(int));
780                                                         if (NULL ==
781                                                             listener_vectevt)
782                                                                 goto out;
783                                                         listener_vectevt_sz +=
784                                                             64;
785                                                 }
786                                                 listener_vectevt
787                                                     [listener_vectevt_idx] =
788                                                     vectevt[vectevt_idx];
789                                                 listener_vectevt_idx++;
790                                         }
791                                         numvalues -= numvalues_processed;
792                                 }
793
794                                 numvalues =
795                                     MRPDU_VECT_NUMVALUES(ntohs
796                                                          (mrpdu_vectorptr->
797                                                           VectorHeader));
798
799                                 /* if not an even multiple ... */
800                                 if (numvalues != ((numvalues / 3) * 3))
801                                         numvectorbytes = (numvalues / 3) + 1;
802                                 else
803                                         numvectorbytes = (numvalues / 3);
804
805                                 listener_vectevt_idx = 0;
806
807                                 for (vectidx = 8;
808                                      vectidx <= (numvectorbytes + 8);
809                                      vectidx++) {
810                                         vect_3pack =
811                                             mrpdu_vectorptr->
812                                             FirstValue_VectorEvents[vectidx];
813                                         vectevt[0] = vect_3pack / 36;
814                                         vectevt[1] =
815                                             (vect_3pack - vectevt[0] * 36) / 6;
816                                         vectevt[2] =
817                                             vect_3pack - (36 * vectevt[0]) -
818                                             (6 * vectevt[1]);
819
820                                         numvalues_processed =
821                                             (numvalues > 3 ? 3 : numvalues);
822
823                                         for (vectevt_idx = 0;
824                                              vectevt_idx < numvalues_processed;
825                                              vectevt_idx++) {
826
827                                                 if (MSRP_LISTENER_IGNORE ==
828                                                     vectevt[vectevt_idx]) {
829                                                         msrp_increment_streamid
830                                                             (streamid_firstval);
831                                                         continue;
832                                                 }
833
834                                                 attrib = msrp_alloc();
835                                                 if (NULL == attrib)
836                                                         goto out;       /* oops - internal error */
837
838                                                 attrib->type =
839                                                     MSRP_LISTENER_TYPE;
840
841                                                 memcpy(attrib->attribute.
842                                                        talk_listen.StreamID,
843                                                        streamid_firstval, 8);
844                                                 attrib->substate =
845                                                     listener_vectevt
846                                                     [listener_vectevt_idx];
847                                                 msrp_increment_streamid
848                                                     (streamid_firstval);
849                                                 listener_vectevt_idx++;
850
851                                                 memcpy(attrib->registrar.
852                                                        macaddr, eth->srcaddr,
853                                                        6);
854
855                                                 switch (vectevt[vectevt_idx]) {
856                                                 case MRPDU_NEW:
857                                                         msrp_event
858                                                             (MRP_EVENT_RNEW,
859                                                              attrib);
860                                                         break;
861                                                 case MRPDU_JOININ:
862                                                         msrp_event
863                                                             (MRP_EVENT_RJOININ,
864                                                              attrib);
865                                                         break;
866                                                 case MRPDU_IN:
867                                                         msrp_event
868                                                             (MRP_EVENT_RIN,
869                                                              attrib);
870                                                         break;
871                                                 case MRPDU_JOINMT:
872                                                         msrp_event
873                                                             (MRP_EVENT_RJOINMT,
874                                                              attrib);
875                                                         break;
876                                                 case MRPDU_MT:
877                                                         msrp_event
878                                                             (MRP_EVENT_RMT,
879                                                              attrib);
880                                                         break;
881                                                 case MRPDU_LV:
882                                                         msrp_event
883                                                             (MRP_EVENT_RLV,
884                                                              attrib);
885                                                         break;
886                                                 default:
887                                                         free(attrib);
888                                                         break;
889                                                 }
890                                         }
891                                         numvalues -= numvalues_processed;
892                                 }
893
894                                 if (MRPDU_VECT_LVA
895                                     (ntohs(mrpdu_vectorptr->VectorHeader)))
896                                         msrp_event(MRP_EVENT_RLA, NULL);
897
898                                 numvalues =
899                                     MRPDU_VECT_NUMVALUES(ntohs
900                                                          (mrpdu_vectorptr->
901                                                           VectorHeader));
902                                 if (numvalues != ((numvalues / 4) * 4))
903                                         numvectorbytes += (numvalues / 4) + 1;
904                                 else
905                                         numvectorbytes += (numvalues / 4);
906
907                                 /* 2 byte numvalues + 8 byte FirstValue + (n) vector bytes */
908                                 mrpdu_msg_ptr = (uint8_t *) mrpdu_vectorptr;
909                                 mrpdu_msg_ptr += 10 + numvectorbytes;
910
911                                 mrpdu_vectorptr =
912                                     (mrpdu_vectorattrib_t *) mrpdu_msg_ptr;
913                         }
914
915                         break;
916                 case MSRP_TALKER_ADV_TYPE:
917                         /* another place where the spec munges with reality ...
918                          * we can start out as a talker advertise type, but can get back
919                          * a talker failed from the bridge in response ... in which
920                          * by the spec we are supposed to merge the talker failed into
921                          * the talker advertise and change the attribute type ...
922                          *
923                          * but also note the spec says that a talker cant change the
924                          * firstvalues definition of a stream without tearing down the
925                          * existing stream, wait two leave-all periods, then re-advertise
926                          * the stream.
927                          */
928                         if (mrpdu_msg->AttributeLength != 25) {
929                                 /* we can seek for an endmark to recover .. but this version
930                                  * dumps the entire packet as malformed
931                                  */
932                                 goto out;
933                         }
934
935                         /* MSRP uses AttributeListLength ...  */
936                         mrpdu_vectorptr =
937                             (mrpdu_vectorattrib_t *)&(mrpdu_msg->Data[2]);
938                         mrpdu_msg_ptr = (uint8_t *) mrpdu_vectorptr;
939
940                         while (!((mrpdu_msg_ptr[0] == 0)
941                                  && (mrpdu_msg_ptr[1] == 0))) {
942                                 numvalues =
943                                     MRPDU_VECT_NUMVALUES(ntohs
944                                                          (mrpdu_vectorptr->
945                                                           VectorHeader));
946
947                                 if (0 == numvalues) {
948                                         /* 2 byte numvalues + 25 byte FirstValue + (0) vector bytes */
949                                         mrpdu_msg_ptr =
950                                             (uint8_t *) mrpdu_vectorptr;
951                                         mrpdu_msg_ptr += 27;
952
953                                         mrpdu_vectorptr =
954                                             (mrpdu_vectorattrib_t *)
955                                             mrpdu_msg_ptr;
956                                         continue;
957                                 }
958                                 if ((mrpdu_vectorptr->FirstValue_VectorEvents +
959                                      numvalues / 3) >= mrpdu_msg_eof) {
960                                         /* Malformed - runs off the end of the pdu */
961                                         printf
962                                             ("bad talker adv PDU too long \n");
963                                         goto out;
964                                 }
965                                 memcpy(streamid_firstval,
966                                        mrpdu_vectorptr->FirstValue_VectorEvents,
967                                        8);
968                                 memcpy(destmac_firstval,
969                                        &
970                                        (mrpdu_vectorptr->FirstValue_VectorEvents
971                                         [8]), 6);
972
973                                 /* if not an even multiple ... */
974                                 if (numvalues != ((numvalues / 3) * 3))
975                                         numvectorbytes = (numvalues / 3) + 1;
976                                 else
977                                         numvectorbytes = (numvalues / 3);
978
979                                 for (vectidx = 25;
980                                      vectidx <= (numvectorbytes + 25);
981                                      vectidx++) {
982                                         vect_3pack =
983                                             mrpdu_vectorptr->
984                                             FirstValue_VectorEvents[vectidx];
985                                         vectevt[0] = vect_3pack / 36;
986                                         vectevt[1] =
987                                             (vect_3pack - vectevt[0] * 36) / 6;
988                                         vectevt[2] =
989                                             vect_3pack - (36 * vectevt[0]) -
990                                             (6 * vectevt[1]);
991
992                                         numvalues_processed =
993                                             (numvalues > 3 ? 3 : numvalues);
994
995                                         for (vectevt_idx = 0;
996                                              vectevt_idx < numvalues_processed;
997                                              vectevt_idx++) {
998
999                                                 attrib = msrp_alloc();
1000                                                 if (NULL == attrib)
1001                                                         goto out;       /* oops - internal error */
1002
1003                                                 attrib->type =
1004                                                     MSRP_TALKER_ADV_TYPE;
1005
1006                                                 /* note this ISNT from us ... */
1007                                                 attrib->direction =
1008                                                     MSRP_DIRECTION_LISTENER;
1009
1010                                                 memcpy(attrib->attribute.
1011                                                        talk_listen.StreamID,
1012                                                        streamid_firstval, 8);
1013                                                 memcpy(attrib->attribute.
1014                                                        talk_listen.
1015                                                        DataFrameParameters.
1016                                                        Dest_Addr,
1017                                                        destmac_firstval, 6);
1018
1019                                                 msrp_increment_streamid
1020                                                     (streamid_firstval);
1021                                                 mmrp_increment_macaddr
1022                                                     (destmac_firstval);
1023
1024                                                 attrib->attribute.talk_listen.
1025                                                     DataFrameParameters.
1026                                                     Vlan_ID =
1027                                                     mrpdu_vectorptr->
1028                                                     FirstValue_VectorEvents[14];
1029                                                 attrib->attribute.talk_listen.
1030                                                     DataFrameParameters.
1031                                                     Vlan_ID <<= 8;
1032                                                 attrib->attribute.talk_listen.
1033                                                     DataFrameParameters.
1034                                                     Vlan_ID |=
1035                                                     mrpdu_vectorptr->
1036                                                     FirstValue_VectorEvents[15];
1037
1038                                                 attrib->attribute.talk_listen.
1039                                                     TSpec.MaxFrameSize =
1040                                                     mrpdu_vectorptr->
1041                                                     FirstValue_VectorEvents[16];
1042                                                 attrib->attribute.talk_listen.
1043                                                     TSpec.MaxFrameSize <<= 8;
1044                                                 attrib->attribute.talk_listen.
1045                                                     TSpec.MaxFrameSize |=
1046                                                     mrpdu_vectorptr->
1047                                                     FirstValue_VectorEvents[17];
1048
1049                                                 attrib->attribute.talk_listen.
1050                                                     TSpec.MaxIntervalFrames =
1051                                                     mrpdu_vectorptr->
1052                                                     FirstValue_VectorEvents[18];
1053                                                 attrib->attribute.talk_listen.
1054                                                     TSpec.
1055                                                     MaxIntervalFrames <<= 8;
1056                                                 attrib->attribute.talk_listen.
1057                                                     TSpec.MaxIntervalFrames |=
1058                                                     mrpdu_vectorptr->
1059                                                     FirstValue_VectorEvents[19];
1060
1061                                                 attrib->attribute.talk_listen.
1062                                                     PriorityAndRank =
1063                                                     mrpdu_vectorptr->
1064                                                     FirstValue_VectorEvents[20];
1065
1066                                                 attrib->attribute.talk_listen.
1067                                                     AccumulatedLatency =
1068                                                     mrpdu_vectorptr->
1069                                                     FirstValue_VectorEvents[21];
1070                                                 attrib->attribute.talk_listen.
1071                                                     AccumulatedLatency <<= 8;
1072                                                 attrib->attribute.talk_listen.
1073                                                     AccumulatedLatency |=
1074                                                     mrpdu_vectorptr->
1075                                                     FirstValue_VectorEvents[22];
1076                                                 attrib->attribute.talk_listen.
1077                                                     AccumulatedLatency <<= 8;
1078                                                 attrib->attribute.talk_listen.
1079                                                     AccumulatedLatency |=
1080                                                     mrpdu_vectorptr->
1081                                                     FirstValue_VectorEvents[23];
1082                                                 attrib->attribute.talk_listen.
1083                                                     AccumulatedLatency <<= 8;
1084                                                 attrib->attribute.talk_listen.
1085                                                     AccumulatedLatency |=
1086                                                     mrpdu_vectorptr->
1087                                                     FirstValue_VectorEvents[24];
1088
1089                                                 memcpy(attrib->registrar.
1090                                                        macaddr, eth->srcaddr,
1091                                                        6);
1092
1093                                                 switch (vectevt[vectevt_idx]) {
1094                                                 case MRPDU_NEW:
1095                                                         msrp_event
1096                                                             (MRP_EVENT_RNEW,
1097                                                              attrib);
1098                                                         break;
1099                                                 case MRPDU_JOININ:
1100                                                         msrp_event
1101                                                             (MRP_EVENT_RJOININ,
1102                                                              attrib);
1103                                                         break;
1104                                                 case MRPDU_IN:
1105                                                         msrp_event
1106                                                             (MRP_EVENT_RIN,
1107                                                              attrib);
1108                                                         break;
1109                                                 case MRPDU_JOINMT:
1110                                                         msrp_event
1111                                                             (MRP_EVENT_RJOINMT,
1112                                                              attrib);
1113                                                         break;
1114                                                 case MRPDU_MT:
1115                                                         msrp_event
1116                                                             (MRP_EVENT_RMT,
1117                                                              attrib);
1118                                                         break;
1119                                                 case MRPDU_LV:
1120                                                         msrp_event
1121                                                             (MRP_EVENT_RLV,
1122                                                              attrib);
1123                                                         break;
1124                                                 default:
1125                                                         free(attrib);
1126                                                         break;
1127                                                 }
1128                                         }
1129                                         numvalues -= numvalues_processed;
1130                                 }
1131
1132                                 if (MRPDU_VECT_LVA
1133                                     (ntohs(mrpdu_vectorptr->VectorHeader)))
1134                                         msrp_event(MRP_EVENT_RLA, NULL);
1135
1136                                 /* 2 byte numvalues + 25 byte FirstValue + (n) vector bytes */
1137                                 mrpdu_msg_ptr = (uint8_t *) mrpdu_vectorptr;
1138                                 mrpdu_msg_ptr += 27 + numvectorbytes;
1139
1140                                 mrpdu_vectorptr =
1141                                     (mrpdu_vectorattrib_t *) mrpdu_msg_ptr;
1142                         }
1143                         break;
1144                 case MSRP_TALKER_FAILED_TYPE:
1145                         if (mrpdu_msg->AttributeLength != 34) {
1146                                 /* we can seek for an endmark to recover .. but this version
1147                                  * dumps the entire packet as malformed
1148                                  */
1149                                 goto out;
1150                         }
1151
1152                         /* MSRP uses AttributeListLength ...  */
1153                         mrpdu_vectorptr =
1154                             (mrpdu_vectorattrib_t *)&(mrpdu_msg->Data[2]);
1155                         mrpdu_msg_ptr = (uint8_t *) mrpdu_vectorptr;
1156                         while (!((mrpdu_msg_ptr[0] == 0)
1157                                  && (mrpdu_msg_ptr[1] == 0))) {
1158                                 numvalues =
1159                                     MRPDU_VECT_NUMVALUES(ntohs
1160                                                          (mrpdu_vectorptr->
1161                                                           VectorHeader));
1162
1163                                 if (0 == numvalues) {
1164                                         /* 2 byte numvalues + 34 byte FirstValue + (0) vector bytes */
1165                                         mrpdu_msg_ptr =
1166                                             (uint8_t *) mrpdu_vectorptr;
1167                                         mrpdu_msg_ptr += 36;
1168                                         mrpdu_vectorptr =
1169                                             (mrpdu_vectorattrib_t *)
1170                                             mrpdu_msg_ptr;
1171                                         continue;
1172                                 }
1173                                 if ((mrpdu_vectorptr->FirstValue_VectorEvents +
1174                                      numvalues / 3) >= mrpdu_msg_eof)
1175                                         /* Malformed - runs off the end of the pdu */
1176                                         goto out;
1177
1178                                 memcpy(streamid_firstval,
1179                                        mrpdu_vectorptr->FirstValue_VectorEvents,
1180                                        8);
1181                                 memcpy(destmac_firstval,
1182                                        &
1183                                        (mrpdu_vectorptr->FirstValue_VectorEvents
1184                                         [8]), 6);
1185
1186                                 /* if not an even multiple ... */
1187                                 if (numvalues != ((numvalues / 3) * 3))
1188                                         numvectorbytes = (numvalues / 3) + 1;
1189                                 else
1190                                         numvectorbytes = (numvalues / 3);
1191
1192                                 for (vectidx = 34;
1193                                      vectidx <= (numvectorbytes + 34);
1194                                      vectidx++) {
1195                                         vect_3pack =
1196                                             mrpdu_vectorptr->
1197                                             FirstValue_VectorEvents[vectidx];
1198                                         vectevt[0] = vect_3pack / 36;
1199                                         vectevt[1] =
1200                                             (vect_3pack - vectevt[0] * 36) / 6;
1201                                         vectevt[2] =
1202                                             vect_3pack - (36 * vectevt[0]) -
1203                                             (6 * vectevt[1]);
1204
1205                                         numvalues_processed =
1206                                             (numvalues > 3 ? 3 : numvalues);
1207
1208                                         for (vectevt_idx = 0;
1209                                              vectevt_idx < numvalues_processed;
1210                                              vectevt_idx++) {
1211
1212                                                 attrib = msrp_alloc();
1213                                                 if (NULL == attrib)
1214                                                         goto out;       /* oops - internal error */
1215                                                 /* update the failure information on merge, but don't support
1216                                                  * different ADV and FAILED_TYPES in the list of attributes */
1217                                                 attrib->type =
1218                                                     MSRP_TALKER_ADV_TYPE;
1219
1220                                                 /* NOTE this isn't from us */
1221                                                 attrib->direction =
1222                                                     MSRP_DIRECTION_LISTENER;
1223
1224                                                 memcpy(attrib->attribute.
1225                                                        talk_listen.StreamID,
1226                                                        streamid_firstval, 8);
1227                                                 memcpy(attrib->attribute.
1228                                                        talk_listen.
1229                                                        DataFrameParameters.
1230                                                        Dest_Addr,
1231                                                        destmac_firstval, 6);
1232
1233                                                 msrp_increment_streamid
1234                                                     (streamid_firstval);
1235                                                 mmrp_increment_macaddr
1236                                                     (destmac_firstval);
1237
1238                                                 attrib->attribute.talk_listen.
1239                                                     DataFrameParameters.
1240                                                     Vlan_ID =
1241                                                     mrpdu_vectorptr->
1242                                                     FirstValue_VectorEvents[14];
1243                                                 attrib->attribute.talk_listen.
1244                                                     DataFrameParameters.
1245                                                     Vlan_ID <<= 8;
1246                                                 attrib->attribute.talk_listen.
1247                                                     DataFrameParameters.
1248                                                     Vlan_ID |=
1249                                                     mrpdu_vectorptr->
1250                                                     FirstValue_VectorEvents[15];
1251
1252                                                 attrib->attribute.talk_listen.
1253                                                     TSpec.MaxFrameSize =
1254                                                     mrpdu_vectorptr->
1255                                                     FirstValue_VectorEvents[16];
1256                                                 attrib->attribute.talk_listen.
1257                                                     TSpec.MaxFrameSize <<= 8;
1258                                                 attrib->attribute.talk_listen.
1259                                                     TSpec.MaxFrameSize |=
1260                                                     mrpdu_vectorptr->
1261                                                     FirstValue_VectorEvents[17];
1262
1263                                                 attrib->attribute.talk_listen.
1264                                                     TSpec.MaxIntervalFrames =
1265                                                     mrpdu_vectorptr->
1266                                                     FirstValue_VectorEvents[18];
1267                                                 attrib->attribute.talk_listen.
1268                                                     TSpec.
1269                                                     MaxIntervalFrames <<= 8;
1270                                                 attrib->attribute.talk_listen.
1271                                                     TSpec.MaxIntervalFrames |=
1272                                                     mrpdu_vectorptr->
1273                                                     FirstValue_VectorEvents[19];
1274
1275                                                 attrib->attribute.talk_listen.
1276                                                     PriorityAndRank =
1277                                                     mrpdu_vectorptr->
1278                                                     FirstValue_VectorEvents[20];
1279
1280                                                 attrib->attribute.talk_listen.
1281                                                     AccumulatedLatency =
1282                                                     mrpdu_vectorptr->
1283                                                     FirstValue_VectorEvents[21];
1284                                                 attrib->attribute.talk_listen.
1285                                                     AccumulatedLatency <<= 8;
1286                                                 attrib->attribute.talk_listen.
1287                                                     AccumulatedLatency |=
1288                                                     mrpdu_vectorptr->
1289                                                     FirstValue_VectorEvents[22];
1290                                                 attrib->attribute.talk_listen.
1291                                                     AccumulatedLatency <<= 8;
1292                                                 attrib->attribute.talk_listen.
1293                                                     AccumulatedLatency |=
1294                                                     mrpdu_vectorptr->
1295                                                     FirstValue_VectorEvents[23];
1296                                                 attrib->attribute.talk_listen.
1297                                                     AccumulatedLatency <<= 8;
1298                                                 attrib->attribute.talk_listen.
1299                                                     AccumulatedLatency |=
1300                                                     mrpdu_vectorptr->
1301                                                     FirstValue_VectorEvents[24];
1302
1303                                                 memcpy(attrib->attribute.
1304                                                        talk_listen.
1305                                                        FailureInformation.
1306                                                        BridgeID,
1307                                                        &(mrpdu_vectorptr->
1308                                                          FirstValue_VectorEvents
1309                                                          [25]), 8);
1310
1311                                                 attrib->attribute.talk_listen.
1312                                                     FailureInformation.
1313                                                     FailureCode =
1314                                                     mrpdu_vectorptr->
1315                                                     FirstValue_VectorEvents[33];
1316
1317                                                 memcpy(attrib->registrar.
1318                                                        macaddr, eth->srcaddr,
1319                                                        6);
1320
1321                                                 switch (vectevt[vectevt_idx]) {
1322                                                 case MRPDU_NEW:
1323                                                         msrp_event
1324                                                             (MRP_EVENT_RNEW,
1325                                                              attrib);
1326                                                         break;
1327                                                 case MRPDU_JOININ:
1328                                                         msrp_event
1329                                                             (MRP_EVENT_RJOININ,
1330                                                              attrib);
1331                                                         break;
1332                                                 case MRPDU_IN:
1333                                                         msrp_event
1334                                                             (MRP_EVENT_RIN,
1335                                                              attrib);
1336                                                         break;
1337                                                 case MRPDU_JOINMT:
1338                                                         msrp_event
1339                                                             (MRP_EVENT_RJOINMT,
1340                                                              attrib);
1341                                                         break;
1342                                                 case MRPDU_MT:
1343                                                         msrp_event
1344                                                             (MRP_EVENT_RMT,
1345                                                              attrib);
1346                                                         break;
1347                                                 case MRPDU_LV:
1348                                                         msrp_event
1349                                                             (MRP_EVENT_RLV,
1350                                                              attrib);
1351                                                         break;
1352                                                 default:
1353                                                         free(attrib);
1354                                                         break;
1355                                                 }
1356                                         }
1357                                         numvalues -= numvalues_processed;
1358                                 }
1359
1360                                 if (MRPDU_VECT_LVA
1361                                     (ntohs(mrpdu_vectorptr->VectorHeader)))
1362                                         msrp_event(MRP_EVENT_RLA, NULL);
1363
1364                                 /* 2 byte numvalues + 34 byte FirstValue + (n) vector bytes */
1365                                 mrpdu_msg_ptr = (uint8_t *) mrpdu_vectorptr;
1366                                 mrpdu_msg_ptr += 36 + numvectorbytes;
1367
1368                                 mrpdu_vectorptr =
1369                                     (mrpdu_vectorattrib_t *) mrpdu_msg_ptr;
1370                         }
1371                         break;
1372                 default:
1373                         /* unrecognized attribute type
1374                          * we can seek for an endmark to recover .. but this version
1375                          * dumps the entire packet as malformed
1376                          */
1377                         printf("unrecognized attribute type (%d)\n",
1378                                mrpdu_msg->AttributeType);
1379                         goto out;
1380                 }
1381         }
1382
1383         if (listener_vectevt)
1384                 free(listener_vectevt);
1385
1386         free(msgbuf);
1387         return 0;
1388  out:
1389         if (listener_vectevt)
1390                 free(listener_vectevt);
1391
1392         free(msgbuf);
1393
1394         return -1;
1395 }
1396
1397 int
1398 msrp_emit_talkvectors(unsigned char *msgbuf, unsigned char *msgbuf_eof,
1399                       int *bytes_used, int lva)
1400 {
1401         mrpdu_vectorattrib_t *mrpdu_vectorptr;
1402         uint16_t numvalues;
1403         uint8_t vect_3pack;
1404         int vectidx;
1405         int vectevt[3];
1406         int vectevt_idx;
1407         uint8_t streamid_firstval[8];
1408         uint8_t destmac_firstval[6];
1409         int attriblistlen;
1410         struct msrp_attribute *attrib, *vattrib;
1411         mrpdu_message_t *mrpdu_msg;
1412         unsigned char *mrpdu_msg_ptr = msgbuf;
1413         unsigned char *mrpdu_msg_eof = msgbuf_eof;
1414         int mac_eq;
1415
1416         /* need at least 28 bytes for a single vector */
1417         if (mrpdu_msg_ptr > (mrpdu_msg_eof - 28))
1418                 goto oops;
1419
1420         /*
1421          * as an endpoint, we don't advertise talker failed attributes (which
1422          * only a listener should receive) - but since this daemon could
1423          * function dual-mode - listening to streams as well as being a talker
1424          * station - we only advertise the talker vectors for declared streams,
1425          * not those we know about as a listener ...
1426          */
1427         mrpdu_msg = (mrpdu_message_t *) mrpdu_msg_ptr;
1428         mrpdu_msg->AttributeType = MSRP_TALKER_ADV_TYPE;
1429         mrpdu_msg->AttributeLength = 25;
1430
1431         attrib = MSRP_db->attrib_list;
1432
1433         mrpdu_vectorptr = (mrpdu_vectorattrib_t *)&(mrpdu_msg->Data[2]);
1434
1435         while ((mrpdu_msg_ptr < (mrpdu_msg_eof - 2)) && (NULL != attrib)) {
1436
1437                 if (MSRP_TALKER_ADV_TYPE != attrib->type) {
1438                         attrib = attrib->next;
1439                         continue;
1440                 }
1441 #ifdef CHECK
1442                 if (MSRP_DIRECTION_LISTENER == attrib->direction) {
1443                         attrib = attrib->next;
1444                         continue;
1445                 }
1446 #endif
1447                 if (0 == attrib->applicant.tx) {
1448                         attrib = attrib->next;
1449                         continue;
1450                 }
1451                 if (MRP_ENCODE_OPTIONAL == attrib->applicant.encode) {
1452                         attrib->applicant.tx = 0;
1453                         attrib = attrib->next;
1454                         continue;
1455                 }
1456
1457                 /* pointing to at least one attribute which needs to be transmitted */
1458                 memcpy(streamid_firstval,
1459                        attrib->attribute.talk_listen.StreamID, 8);
1460                 memcpy(destmac_firstval,
1461                        attrib->attribute.talk_listen.DataFrameParameters.
1462                        Dest_Addr, 6);
1463                 memcpy(mrpdu_vectorptr->FirstValue_VectorEvents,
1464                        streamid_firstval, 8);
1465                 memcpy(&(mrpdu_vectorptr->FirstValue_VectorEvents[8]),
1466                        destmac_firstval, 6);
1467
1468                 mrpdu_vectorptr->FirstValue_VectorEvents[14] =
1469                     attrib->attribute.talk_listen.DataFrameParameters.
1470                     Vlan_ID >> 8;
1471                 mrpdu_vectorptr->FirstValue_VectorEvents[15] =
1472                     (uint8_t) attrib->attribute.talk_listen.
1473                     DataFrameParameters.Vlan_ID;
1474
1475                 mrpdu_vectorptr->FirstValue_VectorEvents[16] =
1476                     attrib->attribute.talk_listen.TSpec.MaxFrameSize >> 8;
1477                 mrpdu_vectorptr->FirstValue_VectorEvents[17] =
1478                     (uint8_t) attrib->attribute.talk_listen.TSpec.MaxFrameSize;
1479
1480                 mrpdu_vectorptr->FirstValue_VectorEvents[18] =
1481                     attrib->attribute.talk_listen.TSpec.MaxIntervalFrames >> 8;
1482                 mrpdu_vectorptr->FirstValue_VectorEvents[19] =
1483                     (uint8_t) attrib->attribute.talk_listen.
1484                     TSpec.MaxIntervalFrames;
1485
1486                 mrpdu_vectorptr->FirstValue_VectorEvents[20] =
1487                     attrib->attribute.talk_listen.PriorityAndRank;
1488
1489                 mrpdu_vectorptr->FirstValue_VectorEvents[21] =
1490                     attrib->attribute.talk_listen.AccumulatedLatency >> 24;
1491                 mrpdu_vectorptr->FirstValue_VectorEvents[22] =
1492                     attrib->attribute.talk_listen.AccumulatedLatency >> 16;
1493                 mrpdu_vectorptr->FirstValue_VectorEvents[23] =
1494                     attrib->attribute.talk_listen.AccumulatedLatency >> 8;
1495                 mrpdu_vectorptr->FirstValue_VectorEvents[24] =
1496                     attrib->attribute.talk_listen.AccumulatedLatency;
1497
1498                 switch (attrib->applicant.sndmsg) {
1499                 case MRP_SND_IN:
1500                         /*
1501                          * If 'In' in indicated by the applicant attribute, the
1502                          * look at the registrar state to determine whether to
1503                          * send an In (if registrar is also In) or an Mt if the
1504                          * registrar is either Mt or Lv.
1505                          */
1506                         if (MRP_IN_STATE == attrib->registrar.mrp_state)
1507                                 vectevt[0] = MRPDU_IN;
1508                         else
1509                                 vectevt[0] = MRPDU_MT;
1510                         break;
1511                 case MRP_SND_NEW:
1512                         vectevt[0] = MRPDU_NEW;
1513                         break;
1514                 case MRP_SND_LV:
1515                         vectevt[0] = MRPDU_LV;
1516                         break;
1517                 case MRP_SND_JOIN:
1518                         /* IF 'Join' in indicated by the applicant, look at
1519                          * the corresponding registrar state to determine whether
1520                          * to send a JoinIn (if the registar state is 'In') or
1521                          * a JoinMt if the registrar state is MT or LV.
1522                          */
1523                         if (MRP_IN_STATE == attrib->registrar.mrp_state)
1524                                 vectevt[0] = MRPDU_JOININ;
1525                         else
1526                                 vectevt[0] = MRPDU_JOINMT;
1527                         break;
1528                 default:
1529                         /* huh? */
1530                         goto oops;
1531                         break;
1532                 }
1533
1534                 vectevt_idx = 1;
1535                 numvalues = 1;
1536                 vectevt[1] = 0;
1537                 vectevt[2] = 0;
1538
1539                 /* now attempt to vectorize contiguous other attributes
1540                  * which also need to be transmitted
1541                  */
1542
1543                 vectidx = 25;
1544                 vattrib = attrib->next;
1545
1546                 while (NULL != vattrib) {
1547                         if (MSRP_TALKER_ADV_TYPE != vattrib->type)
1548                                 break;
1549
1550                         if (0 == vattrib->applicant.tx)
1551                                 break;
1552
1553                         msrp_increment_streamid(streamid_firstval);
1554                         mmrp_increment_macaddr(destmac_firstval);
1555
1556                         mac_eq = memcmp(vattrib->attribute.talk_listen.StreamID,
1557                                         streamid_firstval, 8);
1558
1559                         if (0 != mac_eq)
1560                                 break;
1561
1562                         vattrib->applicant.tx = 0;
1563
1564                         switch (vattrib->applicant.sndmsg) {
1565                         case MRP_SND_IN:
1566                                 /*
1567                                  * If 'In' in indicated by the applicant attribute, the
1568                                  * look at the registrar state to determine whether to
1569                                  * send an In (if registrar is also In) or an Mt if the
1570                                  * registrar is either Mt or Lv.
1571                                  */
1572                                 if (MRP_IN_STATE ==
1573                                     vattrib->registrar.mrp_state)
1574                                         vectevt[vectevt_idx] = MRPDU_IN;
1575                                 else
1576                                         vectevt[vectevt_idx] = MRPDU_MT;
1577                                 break;
1578                         case MRP_SND_NEW:
1579                                 vectevt[vectevt_idx] = MRPDU_NEW;
1580                                 break;
1581                         case MRP_SND_LV:
1582                                 vectevt[vectevt_idx] = MRPDU_LV;
1583                                 break;
1584                         case MRP_SND_JOIN:
1585                                 /* IF 'Join' in indicated by the applicant, look at
1586                                  * the corresponding registrar state to determine whether
1587                                  * to send a JoinIn (if the registar state is 'In') or
1588                                  * a JoinMt if the registrar state is MT or LV.
1589                                  */
1590                                 if (MRP_IN_STATE == attrib->registrar.mrp_state)
1591                                         vectevt[vectevt_idx] = MRPDU_JOININ;
1592                                 else
1593                                         vectevt[vectevt_idx] = MRPDU_JOINMT;
1594                                 break;
1595                         default:
1596                                 /* huh? */
1597                                 goto oops;
1598                                 break;
1599                         }
1600
1601                         vectevt_idx++;
1602                         numvalues++;
1603
1604                         if (vectevt_idx > 2) {
1605                                 vect_3pack = MRPDU_3PACK_ENCODE(vectevt[0],
1606                                                                 vectevt[1],
1607                                                                 vectevt[2]);
1608
1609                                 mrpdu_vectorptr->FirstValue_VectorEvents
1610                                     [vectidx] = vect_3pack;
1611                                 vectidx++;
1612                                 vectevt[0] = 0;
1613                                 vectevt[1] = 0;
1614                                 vectevt[2] = 0;
1615                                 vectevt_idx = 0;
1616                         }
1617
1618                         if (&(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx])
1619                             > (mrpdu_msg_eof - 2))
1620                                 goto oops;
1621
1622                         vattrib = vattrib->next;
1623                 }
1624
1625                 /* handle any trailers */
1626                 if (vectevt_idx > 0) {
1627                         vect_3pack = MRPDU_3PACK_ENCODE(vectevt[0],
1628                                                         vectevt[1], vectevt[2]);
1629
1630                         mrpdu_vectorptr->FirstValue_VectorEvents[vectidx] =
1631                             vect_3pack;
1632                         vectidx++;
1633                 }
1634
1635                 if (&(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx]) >
1636                     (mrpdu_msg_eof - 2))
1637                         goto oops;
1638
1639                 mrpdu_vectorptr->VectorHeader = MRPDU_VECT_NUMVALUES(numvalues);
1640
1641                 if (lva)
1642                         mrpdu_vectorptr->VectorHeader |= MRPDU_VECT_LVA(0xFFFF);
1643
1644                 mrpdu_vectorptr->VectorHeader =
1645                     htons(mrpdu_vectorptr->VectorHeader);
1646
1647                 mrpdu_msg_ptr =
1648                     &(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx]);
1649                 mrpdu_vectorptr = (mrpdu_vectorattrib_t *) mrpdu_msg_ptr;
1650
1651                 attrib = attrib->next;
1652
1653         }
1654
1655         if (mrpdu_vectorptr == (mrpdu_vectorattrib_t *)&(mrpdu_msg->Data[2])) {
1656                 *bytes_used = 0;
1657                 return 0;
1658         }
1659
1660         /* endmark */
1661         *mrpdu_msg_ptr = 0;
1662         mrpdu_msg_ptr++;
1663         *mrpdu_msg_ptr = 0;
1664         mrpdu_msg_ptr++;
1665
1666         *bytes_used = (mrpdu_msg_ptr - msgbuf);
1667
1668         attriblistlen = mrpdu_msg_ptr - &(mrpdu_msg->Data[2]);
1669         mrpdu_msg->Data[0] = (uint8_t) (attriblistlen >> 8);
1670         mrpdu_msg->Data[1] = (uint8_t) attriblistlen;
1671         return 0;
1672  oops:
1673         /* an internal error - caller should assume TXLAF */
1674         *bytes_used = 0;
1675         return -1;
1676 }
1677
1678 int
1679 msrp_emit_listenvectors(unsigned char *msgbuf, unsigned char *msgbuf_eof,
1680                         int *bytes_used, int lva)
1681 {
1682         mrpdu_vectorattrib_t *mrpdu_vectorptr;
1683         mrpdu_message_t *mrpdu_msg;
1684         unsigned char *mrpdu_msg_ptr = msgbuf;
1685         unsigned char *mrpdu_msg_eof = msgbuf_eof;
1686         uint16_t numvalues;
1687         uint8_t vect_3pack;
1688         uint8_t vect_4pack;
1689         int vectidx;
1690         int attriblistlen;
1691         int vectevt[4];
1692         int vectevt_idx;
1693         int *listen_declare = NULL;
1694         int listen_declare_sz = 64;
1695         int listen_declare_idx = 0;
1696         int listen_declare_end = 0;
1697         uint8_t streamid_firstval[8];
1698         struct msrp_attribute *attrib, *vattrib;
1699         int mac_eq;
1700
1701         /* need at least 13 bytes for a single vector */
1702         if (mrpdu_msg_ptr > (mrpdu_msg_eof - 13))
1703                 goto oops;
1704
1705         mrpdu_msg = (mrpdu_message_t *) mrpdu_msg_ptr;
1706         mrpdu_msg->AttributeType = MSRP_LISTENER_TYPE;
1707         mrpdu_msg->AttributeLength = 8;
1708
1709         listen_declare = (int *)malloc(listen_declare_sz * sizeof(int));
1710         if (NULL == listen_declare)
1711                 goto oops;
1712
1713         attrib = MSRP_db->attrib_list;
1714
1715         mrpdu_vectorptr = (mrpdu_vectorattrib_t *)&(mrpdu_msg->Data[2]);
1716
1717         while ((mrpdu_msg_ptr < (mrpdu_msg_eof - 2)) && (NULL != attrib)) {
1718
1719                 if (MSRP_LISTENER_TYPE != attrib->type) {
1720                         attrib = attrib->next;
1721                         continue;
1722                 }
1723
1724                 listen_declare_idx = 0;
1725
1726                 /* if we have a listener type registered, we always will
1727                  * send out an update. We also don't bother trying to
1728                  * insert IGNORES between stream IDs - we only send out
1729                  * contiguous active streams in messages
1730                  */
1731
1732                 /* pointing to at least one attribute which needs to be transmitted */
1733                 memcpy(streamid_firstval,
1734                        attrib->attribute.talk_listen.StreamID, 8);
1735                 memcpy(&(mrpdu_vectorptr->FirstValue_VectorEvents),
1736                        attrib->attribute.talk_listen.StreamID, 8);
1737
1738                 switch (attrib->applicant.sndmsg) {
1739                 case MRP_SND_IN:
1740                         /*
1741                          * If 'In' in indicated by the applicant attribute, the
1742                          * look at the registrar state to determine whether to
1743                          * send an In (if registrar is also In) or an Mt if the
1744                          * registrar is either Mt or Lv.
1745                          */
1746                         if (MRP_IN_STATE == attrib->registrar.mrp_state)
1747                                 vectevt[0] = MRPDU_IN;
1748                         else
1749                                 vectevt[0] = MRPDU_MT;
1750                         break;
1751                 case MRP_SND_NEW:
1752                         vectevt[0] = MRPDU_NEW;
1753                         break;
1754                 case MRP_SND_LV:
1755                         vectevt[0] = MRPDU_LV;
1756                         break;
1757                 case MRP_SND_JOIN:
1758                         /* IF 'Join' in indicated by the applicant, look at
1759                          * the corresponding registrar state to determine whether
1760                          * to send a JoinIn (if the registar state is 'In') or
1761                          * a JoinMt if the registrar state is MT or LV.
1762                          */
1763                         if (MRP_IN_STATE == attrib->registrar.mrp_state)
1764                                 vectevt[0] = MRPDU_JOININ;
1765                         else
1766                                 vectevt[0] = MRPDU_JOINMT;
1767                         break;
1768                 default:
1769                         /* huh? */
1770                         goto oops;
1771                         break;
1772                 }
1773
1774                 vectevt_idx = 1;
1775                 numvalues = 1;
1776                 vectevt[1] = 0;
1777                 vectevt[2] = 0;
1778
1779                 if (listen_declare_sz == (listen_declare_idx + 1)) {
1780                         listen_declare =
1781                             (int *)realloc(listen_declare,
1782                                            (64 +
1783                                             listen_declare_sz) * sizeof(int));
1784                         if (NULL == listen_declare)
1785                                 goto oops;
1786
1787                         listen_declare_sz += 64;
1788                 }
1789
1790                 listen_declare[listen_declare_idx] = attrib->substate;
1791                 listen_declare_idx++;
1792
1793                 /* now attempt to vectorize contiguous other attributes
1794                  * which also need to be transmitted
1795                  */
1796
1797                 vectidx = 8;
1798                 vattrib = attrib->next;
1799
1800                 while (NULL != vattrib) {
1801                         if (MSRP_LISTENER_TYPE != vattrib->type)
1802                                 break;
1803
1804                         if (0 == vattrib->applicant.tx)
1805                                 break;
1806
1807                         msrp_increment_streamid(streamid_firstval);
1808
1809                         mac_eq = memcmp(vattrib->attribute.talk_listen.StreamID,
1810                                         streamid_firstval, 8);
1811
1812                         if (0 != mac_eq)
1813                                 break;
1814
1815                         vattrib->applicant.tx = 0;
1816
1817                         switch (vattrib->applicant.sndmsg) {
1818                         case MRP_SND_IN:
1819                                 /*
1820                                  * If 'In' in indicated by the applicant attribute, the
1821                                  * look at the registrar state to determine whether to
1822                                  * send an In (if registrar is also In) or an Mt if the
1823                                  * registrar is either Mt or Lv.
1824                                  */
1825                                 if (MRP_IN_STATE ==
1826                                     vattrib->registrar.mrp_state)
1827                                         vectevt[vectevt_idx] = MRPDU_IN;
1828                                 else
1829                                         vectevt[vectevt_idx] = MRPDU_MT;
1830                                 break;
1831                         case MRP_SND_NEW:
1832                                 vectevt[vectevt_idx] = MRPDU_NEW;
1833                                 break;
1834                         case MRP_SND_LV:
1835                                 vectevt[vectevt_idx] = MRPDU_LV;
1836                                 break;
1837                         case MRP_SND_JOIN:
1838                                 /* IF 'Join' in indicated by the applicant, look at
1839                                  * the corresponding registrar state to determine whether
1840                                  * to send a JoinIn (if the registar state is 'In') or
1841                                  * a JoinMt if the registrar state is MT or LV.
1842                                  */
1843                                 if (MRP_IN_STATE == attrib->registrar.mrp_state)
1844                                         vectevt[vectevt_idx] = MRPDU_JOININ;
1845                                 else
1846                                         vectevt[vectevt_idx] = MRPDU_JOINMT;
1847                                 break;
1848                         default:
1849                                 /* huh? */
1850                                 goto oops;
1851                                 break;
1852                         }
1853
1854                         vectevt_idx++;
1855                         numvalues++;
1856
1857                         if (listen_declare_sz == (listen_declare_idx + 1)) {
1858                                 listen_declare =
1859                                     (int *)realloc(listen_declare,
1860                                                    (64 +
1861                                                     listen_declare_sz) *
1862                                                    sizeof(int));
1863                                 listen_declare_sz += 64;
1864                         }
1865
1866                         listen_declare[listen_declare_idx] = vattrib->substate;
1867                         listen_declare_idx++;
1868
1869                         if (vectevt_idx > 2) {
1870                                 vect_3pack = MRPDU_3PACK_ENCODE(vectevt[0],
1871                                                                 vectevt[1],
1872                                                                 vectevt[2]);
1873
1874                                 mrpdu_vectorptr->FirstValue_VectorEvents
1875                                     [vectidx] = vect_3pack;
1876                                 vectidx++;
1877                                 vectevt[0] = 0;
1878                                 vectevt[1] = 0;
1879                                 vectevt[2] = 0;
1880                                 vectevt_idx = 0;
1881                         }
1882
1883                         if (&(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx])
1884                             > (mrpdu_msg_eof - 2))
1885                                 goto oops;
1886
1887                         vattrib = vattrib->next;
1888                 }
1889
1890                 /* handle any trailers */
1891                 if (vectevt_idx > 0) {
1892                         vect_3pack = MRPDU_3PACK_ENCODE(vectevt[0],
1893                                                         vectevt[1], vectevt[2]);
1894
1895                         mrpdu_vectorptr->FirstValue_VectorEvents[vectidx] =
1896                             vect_3pack;
1897                         vectidx++;
1898                 }
1899
1900                 /* now emit the 4-packed events */
1901
1902                 listen_declare_end = listen_declare_idx;
1903
1904                 for (listen_declare_idx = 0;
1905                      listen_declare_idx < ((listen_declare_end / 4) * 4);
1906                      listen_declare_idx += 4) {
1907
1908                         if (&(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx])
1909                             > (mrpdu_msg_eof - 2))
1910                                 goto oops;
1911
1912                         if (vectevt_idx > 3) {
1913                                 vect_4pack =
1914                                     MRPDU_4PACK_ENCODE(listen_declare
1915                                                        [listen_declare_idx],
1916                                                        listen_declare
1917                                                        [listen_declare_idx + 1],
1918                                                        listen_declare
1919                                                        [listen_declare_idx + 2],
1920                                                        listen_declare
1921                                                        [listen_declare_idx +
1922                                                         3]);
1923
1924                                 mrpdu_vectorptr->FirstValue_VectorEvents
1925                                     [vectidx] = vect_4pack;
1926                                 vectidx++;
1927                         }
1928
1929                         if (&(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx])
1930                             > (mrpdu_msg_eof - 3))
1931                                 goto oops;
1932
1933                 }
1934
1935                 /* handle any trailers */
1936                 vectevt_idx = 0;
1937                 while (listen_declare_idx < listen_declare_end) {
1938                         vectevt[vectevt_idx] =
1939                             listen_declare[listen_declare_idx];
1940                         listen_declare_idx++;
1941                         vectevt_idx++;
1942                 }
1943                 if (vectevt_idx) {
1944                         vect_4pack = MRPDU_4PACK_ENCODE(vectevt[0],
1945                                                         vectevt[1],
1946                                                         vectevt[2], vectevt[3]);
1947
1948                         mrpdu_vectorptr->FirstValue_VectorEvents[vectidx] =
1949                             vect_4pack;
1950                         vectidx++;
1951                 }
1952
1953                 if (&(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx]) >
1954                     (mrpdu_msg_eof - 2))
1955                         goto oops;
1956
1957                 mrpdu_vectorptr->VectorHeader = MRPDU_VECT_NUMVALUES(numvalues);
1958
1959                 if (lva)
1960                         mrpdu_vectorptr->VectorHeader |= MRPDU_VECT_LVA(0xFFFF);
1961
1962                 mrpdu_vectorptr->VectorHeader =
1963                     htons(mrpdu_vectorptr->VectorHeader);
1964
1965                 mrpdu_msg_ptr =
1966                     &(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx]);
1967
1968                 attrib = attrib->next;
1969
1970                 mrpdu_vectorptr = (mrpdu_vectorattrib_t *) mrpdu_msg_ptr;
1971         }
1972
1973         if (mrpdu_vectorptr == (mrpdu_vectorattrib_t *)&(mrpdu_msg->Data[2])) {
1974                 if (listen_declare)
1975                         free(listen_declare);
1976                 *bytes_used = 0;
1977                 return 0;
1978         }
1979
1980         /* endmark */
1981         *mrpdu_msg_ptr = 0;
1982         mrpdu_msg_ptr++;
1983         *mrpdu_msg_ptr = 0;
1984         mrpdu_msg_ptr++;
1985
1986         *bytes_used = (mrpdu_msg_ptr - msgbuf);
1987
1988         attriblistlen = mrpdu_msg_ptr - &(mrpdu_msg->Data[2]);
1989         mrpdu_msg->Data[0] = (uint8_t) (attriblistlen >> 8);
1990         mrpdu_msg->Data[1] = (uint8_t) attriblistlen;
1991
1992         free(listen_declare);
1993         return 0;
1994  oops:
1995         /* an internal error - caller should assume TXLAF */
1996         if (listen_declare)
1997                 free(listen_declare);
1998         *bytes_used = 0;
1999         return -1;
2000 }
2001
2002 int msrp_txpdu(void)
2003 {
2004         unsigned char *msgbuf, *msgbuf_wrptr;
2005         int msgbuf_len;
2006         int bytes = 0;
2007         eth_hdr_t *eth;
2008         mrpdu_t *mrpdu;
2009         unsigned char *mrpdu_msg_ptr;
2010         unsigned char *mrpdu_msg_eof;
2011         int rc;
2012         int lva = 0;
2013
2014         msgbuf = (unsigned char *)malloc(MAX_FRAME_SIZE);
2015         if (NULL == msgbuf)
2016                 return -1;
2017         msgbuf_len = 0;
2018
2019         msgbuf_wrptr = msgbuf;
2020
2021         eth = (eth_hdr_t *) msgbuf_wrptr;
2022
2023         /* note that MSRP frames should always be untagged (no vlan) */
2024         eth->typelen = htons(MSRP_ETYPE);
2025         memcpy(eth->destaddr, MSRP_ADDR, sizeof(eth->destaddr));
2026         memcpy(eth->srcaddr, STATION_ADDR, sizeof(eth->srcaddr));
2027
2028         msgbuf_wrptr += sizeof(eth_hdr_t);
2029
2030         mrpdu = (mrpdu_t *) msgbuf_wrptr;
2031
2032         mrpdu->ProtocolVersion = MSRP_PROT_VER;
2033         mrpdu_msg_ptr = MRPD_GET_MRPDU_MESSAGE_LIST(mrpdu);
2034         mrpdu_msg_eof = (unsigned char *)msgbuf + MAX_FRAME_SIZE;
2035
2036         if (MSRP_db->mrp_db.lva.tx) {
2037                 lva = 1;
2038                 MSRP_db->mrp_db.lva.tx = 0;
2039         }
2040
2041         rc = msrp_emit_talkvectors(mrpdu_msg_ptr, mrpdu_msg_eof, &bytes, lva);
2042         if (-1 == rc)
2043                 goto out;
2044
2045         mrpdu_msg_ptr += bytes;
2046
2047         if (mrpdu_msg_ptr >= (mrpdu_msg_eof - 2))
2048                 goto out;
2049
2050         rc = msrp_emit_listenvectors(mrpdu_msg_ptr, mrpdu_msg_eof, &bytes, lva);
2051         if (-1 == rc)
2052                 goto out;
2053
2054         mrpdu_msg_ptr += bytes;
2055
2056         if (mrpdu_msg_ptr == MRPD_GET_MRPDU_MESSAGE_LIST(mrpdu)) {
2057                 goto out;       /* nothing to send */
2058         }
2059
2060         /* endmark */
2061         if (mrpdu_msg_ptr < (mrpdu_msg_eof - 2)) {
2062                 *mrpdu_msg_ptr = 0;
2063                 mrpdu_msg_ptr++;
2064                 *mrpdu_msg_ptr = 0;
2065                 mrpdu_msg_ptr++;
2066         } else
2067                 goto out;
2068
2069         msgbuf_len = mrpdu_msg_ptr - msgbuf;
2070
2071         bytes = mrpd_send(msrp_socket, msgbuf, msgbuf_len, 0);
2072         if (bytes <= 0)
2073                 goto out;
2074
2075         free(msgbuf);
2076         return 0;
2077  out:
2078         free(msgbuf);
2079         /* caller should assume TXLAF */
2080         return -1;
2081 }
2082
2083 int msrp_send_notifications(struct msrp_attribute *attrib, int notify)
2084 {
2085         char *msgbuf;
2086         char *stage;
2087         char *variant;
2088         char *regsrc;
2089         client_t *client;
2090
2091         if (NULL == attrib)
2092                 return -1;
2093
2094         msgbuf = (char *)malloc(MAX_MRPD_CMDSZ);
2095         if (NULL == msgbuf)
2096                 return -1;
2097
2098         stage = variant = regsrc = NULL;
2099
2100         stage = (char *)malloc(128);
2101         variant = (char *)malloc(128);
2102         regsrc = (char *)malloc(128);
2103
2104         if ((NULL == stage) || (NULL == variant) || (NULL == regsrc))
2105                 goto free_msgbuf;
2106
2107         memset(msgbuf, 0, MAX_MRPD_CMDSZ);
2108
2109         if (MSRP_LISTENER_TYPE == attrib->type) {
2110                 sprintf(variant, "L:D=%d,S=%02x%02x%02x%02x%02x%02x%02x%02x",
2111                         attrib->substate,
2112                         attrib->attribute.talk_listen.StreamID[0],
2113                         attrib->attribute.talk_listen.StreamID[1],
2114                         attrib->attribute.talk_listen.StreamID[2],
2115                         attrib->attribute.talk_listen.StreamID[3],
2116                         attrib->attribute.talk_listen.StreamID[4],
2117                         attrib->attribute.talk_listen.StreamID[5],
2118                         attrib->attribute.talk_listen.StreamID[6],
2119                         attrib->attribute.talk_listen.StreamID[7]);
2120         } else if (MSRP_DOMAIN_TYPE == attrib->type) {
2121                 sprintf(variant, "D:C=%d,P=%d,V=%04x",
2122                         attrib->attribute.domain.SRclassID,
2123                         attrib->attribute.domain.SRclassPriority,
2124                         attrib->attribute.domain.SRclassVID);
2125         } else {
2126                 sprintf(variant, "T:S=%02x%02x%02x%02x%02x%02x%02x%02x"
2127                         ",A=%02x%02x%02x%02x%02x%02x"
2128                         ",V=%04x"
2129                         ",Z=%d"
2130                         ",I=%d"
2131                         ",P=%d"
2132                         ",L=%d"
2133                         ",B=%02x%02x%02x%02x%02x%02x%02x%02x"
2134                         ",C=%d",
2135                         attrib->attribute.talk_listen.StreamID[0],
2136                         attrib->attribute.talk_listen.StreamID[1],
2137                         attrib->attribute.talk_listen.StreamID[2],
2138                         attrib->attribute.talk_listen.StreamID[3],
2139                         attrib->attribute.talk_listen.StreamID[4],
2140                         attrib->attribute.talk_listen.StreamID[5],
2141                         attrib->attribute.talk_listen.StreamID[6],
2142                         attrib->attribute.talk_listen.StreamID[7],
2143                         attrib->attribute.talk_listen.DataFrameParameters.
2144                         Dest_Addr[0],
2145                         attrib->attribute.talk_listen.DataFrameParameters.
2146                         Dest_Addr[1],
2147                         attrib->attribute.talk_listen.DataFrameParameters.
2148                         Dest_Addr[2],
2149                         attrib->attribute.talk_listen.DataFrameParameters.
2150                         Dest_Addr[3],
2151                         attrib->attribute.talk_listen.DataFrameParameters.
2152                         Dest_Addr[4],
2153                         attrib->attribute.talk_listen.DataFrameParameters.
2154                         Dest_Addr[5],
2155                         attrib->attribute.talk_listen.DataFrameParameters.
2156                         Vlan_ID,
2157                         attrib->attribute.talk_listen.TSpec.MaxFrameSize,
2158                         attrib->attribute.talk_listen.TSpec.MaxIntervalFrames,
2159                         attrib->attribute.talk_listen.PriorityAndRank,
2160                         attrib->attribute.talk_listen.AccumulatedLatency,
2161                         attrib->attribute.talk_listen.FailureInformation.
2162                         BridgeID[0],
2163                         attrib->attribute.talk_listen.FailureInformation.
2164                         BridgeID[1],
2165                         attrib->attribute.talk_listen.FailureInformation.
2166                         BridgeID[2],
2167                         attrib->attribute.talk_listen.FailureInformation.
2168                         BridgeID[3],
2169                         attrib->attribute.talk_listen.FailureInformation.
2170                         BridgeID[4],
2171                         attrib->attribute.talk_listen.FailureInformation.
2172                         BridgeID[5],
2173                         attrib->attribute.talk_listen.FailureInformation.
2174                         BridgeID[6],
2175                         attrib->attribute.talk_listen.FailureInformation.
2176                         BridgeID[7],
2177                         attrib->attribute.talk_listen.FailureInformation.
2178                         FailureCode);
2179         }
2180
2181         sprintf(regsrc, "R=%02x%02x%02x%02x%02x%02x",
2182                 attrib->registrar.macaddr[0],
2183                 attrib->registrar.macaddr[1],
2184                 attrib->registrar.macaddr[2],
2185                 attrib->registrar.macaddr[3],
2186                 attrib->registrar.macaddr[4], attrib->registrar.macaddr[5]);
2187
2188         switch (notify) {
2189         case MRP_NOTIFY_NEW:
2190                 sprintf(msgbuf, "SNE %s %s", variant, regsrc);
2191                 break;
2192         case MRP_NOTIFY_JOIN:
2193                 sprintf(msgbuf, "SJO %s %s", variant, regsrc);
2194                 break;
2195         case MRP_NOTIFY_LV:
2196                 sprintf(msgbuf, "SLE %s %s", variant, regsrc);
2197                 break;
2198         default:
2199                 goto free_msgbuf;
2200                 break;
2201         }
2202
2203         client = MSRP_db->mrp_db.clients;
2204         while (NULL != client) {
2205                 mrpd_send_ctl_msg(&(client->client), msgbuf, MAX_MRPD_CMDSZ);
2206                 client = client->next;
2207         }
2208
2209  free_msgbuf:
2210         if (regsrc)
2211                 free(regsrc);
2212         if (variant)
2213                 free(variant);
2214         if (stage)
2215                 free(stage);
2216         free(msgbuf);
2217         return 0;
2218 }
2219
2220 int msrp_dumptable(struct sockaddr_in *client)
2221 {
2222         char *msgbuf;
2223         char *msgbuf_wrptr;
2224         char *stage;
2225         char *variant;
2226         char *regsrc;
2227         struct msrp_attribute *attrib;
2228         char mrp_state[8];
2229
2230         msgbuf = (char *)malloc(MAX_MRPD_CMDSZ);
2231         if (NULL == msgbuf)
2232                 return -1;
2233
2234         stage = variant = regsrc = NULL;
2235
2236         stage = (char *)malloc(128);
2237         variant = (char *)malloc(128);
2238         regsrc = (char *)malloc(128);
2239
2240         if ((NULL == stage) || (NULL == variant) || (NULL == regsrc))
2241                 goto free_msgbuf;
2242
2243         memset(msgbuf, 0, MAX_MRPD_CMDSZ);
2244
2245         msgbuf_wrptr = msgbuf;
2246
2247         attrib = MSRP_db->attrib_list;
2248
2249         while (NULL != attrib) {
2250                 if (MSRP_LISTENER_TYPE == attrib->type) {
2251                         sprintf(variant,
2252                                 "L:D=%d,S=%02x%02x%02x%02x%02x%02x%02x%02x",
2253                                 attrib->substate,
2254                                 attrib->attribute.talk_listen.StreamID[0],
2255                                 attrib->attribute.talk_listen.StreamID[1],
2256                                 attrib->attribute.talk_listen.StreamID[2],
2257                                 attrib->attribute.talk_listen.StreamID[3],
2258                                 attrib->attribute.talk_listen.StreamID[4],
2259                                 attrib->attribute.talk_listen.StreamID[5],
2260                                 attrib->attribute.talk_listen.StreamID[6],
2261                                 attrib->attribute.talk_listen.StreamID[7]);
2262                 } else if (MSRP_DOMAIN_TYPE == attrib->type) {
2263                         sprintf(variant, "D:C=%d,P=%d,V:%04x",
2264                                 attrib->attribute.domain.SRclassID,
2265                                 attrib->attribute.domain.SRclassPriority,
2266                                 attrib->attribute.domain.SRclassVID);
2267                 } else {
2268                         sprintf(variant, "T:S=%02x%02x%02x%02x%02x%02x%02x%02x"
2269                                 ",A=%02x%02x%02x%02x%02x%02x"
2270                                 ",V=%04x"
2271                                 ",Z=%d"
2272                                 ",I=%d"
2273                                 ",P=%d"
2274                                 ",L=%d"
2275                                 ",B=%02x%02x%02x%02x%02x%02x%02x%02x"
2276                                 ",C=%d",
2277                                 attrib->attribute.talk_listen.StreamID[0],
2278                                 attrib->attribute.talk_listen.StreamID[1],
2279                                 attrib->attribute.talk_listen.StreamID[2],
2280                                 attrib->attribute.talk_listen.StreamID[3],
2281                                 attrib->attribute.talk_listen.StreamID[4],
2282                                 attrib->attribute.talk_listen.StreamID[5],
2283                                 attrib->attribute.talk_listen.StreamID[6],
2284                                 attrib->attribute.talk_listen.StreamID[7],
2285                                 attrib->attribute.talk_listen.
2286                                 DataFrameParameters.Dest_Addr[0],
2287                                 attrib->attribute.talk_listen.
2288                                 DataFrameParameters.Dest_Addr[1],
2289                                 attrib->attribute.talk_listen.
2290                                 DataFrameParameters.Dest_Addr[2],
2291                                 attrib->attribute.talk_listen.
2292                                 DataFrameParameters.Dest_Addr[3],
2293                                 attrib->attribute.talk_listen.
2294                                 DataFrameParameters.Dest_Addr[4],
2295                                 attrib->attribute.talk_listen.
2296                                 DataFrameParameters.Dest_Addr[5],
2297                                 attrib->attribute.talk_listen.
2298                                 DataFrameParameters.Vlan_ID,
2299                                 attrib->attribute.talk_listen.TSpec.
2300                                 MaxFrameSize,
2301                                 attrib->attribute.talk_listen.TSpec.
2302                                 MaxIntervalFrames,
2303                                 attrib->attribute.talk_listen.PriorityAndRank,
2304                                 attrib->attribute.talk_listen.
2305                                 AccumulatedLatency,
2306                                 attrib->attribute.talk_listen.
2307                                 FailureInformation.BridgeID[0],
2308                                 attrib->attribute.talk_listen.
2309                                 FailureInformation.BridgeID[1],
2310                                 attrib->attribute.talk_listen.
2311                                 FailureInformation.BridgeID[2],
2312                                 attrib->attribute.talk_listen.
2313                                 FailureInformation.BridgeID[3],
2314                                 attrib->attribute.talk_listen.
2315                                 FailureInformation.BridgeID[4],
2316                                 attrib->attribute.talk_listen.
2317                                 FailureInformation.BridgeID[5],
2318                                 attrib->attribute.talk_listen.
2319                                 FailureInformation.BridgeID[6],
2320                                 attrib->attribute.talk_listen.
2321                                 FailureInformation.BridgeID[7],
2322                                 attrib->attribute.talk_listen.
2323                                 FailureInformation.FailureCode);
2324                 }
2325
2326                 mrp_decode_state(&attrib->registrar, &attrib->applicant,
2327                                  mrp_state, sizeof(mrp_state));
2328
2329                 sprintf(regsrc, "R=%02x%02x%02x%02x%02x%02x %s",
2330                         attrib->registrar.macaddr[0],
2331                         attrib->registrar.macaddr[1],
2332                         attrib->registrar.macaddr[2],
2333                         attrib->registrar.macaddr[3],
2334                         attrib->registrar.macaddr[4],
2335                         attrib->registrar.macaddr[5], mrp_state);
2336
2337                 sprintf(stage, "%s %s\n", variant, regsrc);
2338
2339                 sprintf(msgbuf_wrptr, "%s", stage);
2340                 msgbuf_wrptr += strlen(stage);
2341                 attrib = attrib->next;
2342         }
2343
2344         mrpd_send_ctl_msg(client, msgbuf, MAX_MRPD_CMDSZ);
2345
2346  free_msgbuf:
2347         if (regsrc)
2348                 free(regsrc);
2349         if (variant)
2350                 free(variant);
2351         if (stage)
2352                 free(stage);
2353         free(msgbuf);
2354         return 0;
2355
2356 }
2357
2358 /* S+? - (re)JOIN a stream */
2359 /* S++ - NEW a stream      */
2360 int msrp_cmd_parse_join_or_new_stream(
2361                 char *buf, int buflen,
2362                 struct msrpdu_talker_fail *talker_ad,
2363                 int *err_index
2364 )
2365 {
2366         struct parse_param specs[] = {
2367                 {"S" PARSE_ASSIGN, parse_c64, talker_ad->StreamID},
2368                 {"A" PARSE_ASSIGN, parse_mac, talker_ad->DataFrameParameters.Dest_Addr},
2369                 {"V" PARSE_ASSIGN, parse_u16, &talker_ad->DataFrameParameters.Vlan_ID},
2370                 {"Z" PARSE_ASSIGN, parse_u16, &talker_ad->TSpec.MaxFrameSize},
2371                 {"I" PARSE_ASSIGN, parse_u16, &talker_ad->TSpec.MaxIntervalFrames},
2372                 {"P" PARSE_ASSIGN, parse_u8, &talker_ad->PriorityAndRank},
2373                 {"L" PARSE_ASSIGN, parse_u32, &talker_ad->AccumulatedLatency},
2374                 {0, parse_null, 0}
2375         };
2376         if (buflen < 22)
2377                 return -1;
2378         memset(talker_ad, 0, sizeof(*talker_ad));
2379         return parse(buf + 4, buflen - 4, specs, err_index);
2380 }
2381
2382
2383 /*
2384  * Required fields are:
2385  * talker_ad->StreamID
2386  * talker_ad->DataFrameParameters.Dest_Addr
2387  * talker_ad->DataFrameParameters.Vlan_ID
2388  * talker_ad->TSpec.MaxFrameSize
2389  * talker_ad->TSpec.MaxIntervalFrames
2390  * talker_ad->PriorityAndRank
2391  * talker_ad->AccumulatedLatency
2392  *
2393  */
2394
2395 int msrp_cmd_join_or_new_stream(
2396                 int join,
2397                 struct msrpdu_talker_fail *talker_ad
2398 )
2399 {
2400         struct msrp_attribute *attrib;
2401
2402         attrib = msrp_alloc();
2403         if (NULL == attrib) {
2404                 return -1;
2405         }
2406         attrib->type = MSRP_TALKER_ADV_TYPE;
2407         attrib->attribute.talk_listen = *talker_ad;
2408
2409         if (join)
2410                 msrp_event(MRP_EVENT_JOIN, attrib);
2411         else
2412                 msrp_event(MRP_EVENT_NEW, attrib);
2413
2414         return 0;
2415 }
2416
2417 /* S-- - LV a stream */
2418 int msrp_cmd_parse_leave_stream(
2419                 char *buf, int buflen,
2420                 struct msrpdu_talker_fail *talker_ad,
2421                 int *err_index
2422 )
2423 {
2424         struct parse_param specs[] = {
2425                 {"S" PARSE_ASSIGN, parse_c64, talker_ad->StreamID},
2426                 {0, parse_null, 0}
2427         };
2428         if (buflen < 22)
2429                 return -1;
2430         memset(talker_ad, 0, sizeof(*talker_ad));
2431         return parse(buf + 4, buflen - 4, specs, err_index);
2432 }
2433
2434 int msrp_cmd_leave_stream(
2435                 struct msrpdu_talker_fail *talker_ad
2436 )
2437 {
2438         struct msrp_attribute *attrib;
2439
2440         attrib = msrp_alloc();
2441         if (NULL == attrib) {
2442                 return -1;
2443         }
2444         attrib->type = MSRP_TALKER_ADV_TYPE;
2445         attrib->attribute.talk_listen = *talker_ad;
2446         msrp_event(MRP_EVENT_LV, attrib);
2447
2448         return 0;
2449 }
2450
2451 /* S+L   Report a listener status */
2452 int msrp_cmd_parse_report_listener_status(
2453                 char *buf, int buflen,
2454                 struct msrpdu_talker_fail *talker_ad,
2455                 uint32_t *substate,
2456                 int *err_index
2457 )
2458 {
2459         struct parse_param specs[] = {
2460                 {"L" PARSE_ASSIGN, parse_c64, talker_ad->StreamID},
2461                 {"D" PARSE_ASSIGN, parse_u32, substate},
2462                 {0, parse_null, 0}
2463         };
2464         if (buflen < 26)
2465                 return -1;
2466         memset(talker_ad, 0, sizeof(*talker_ad));
2467         return parse(buf + 4, buflen - 4, specs, err_index);
2468 }
2469
2470 int msrp_cmd_report_listener_status(
2471                 struct msrpdu_talker_fail *talker_ad,
2472                 uint32_t substate
2473 )
2474 {
2475         struct msrp_attribute *attrib;
2476
2477         attrib = msrp_alloc();
2478         if (NULL == attrib) {
2479                 return -1;
2480         }
2481         attrib->type = MSRP_LISTENER_TYPE;
2482         attrib->direction = MSRP_DIRECTION_LISTENER;
2483         attrib->substate = substate;
2484         attrib->attribute.talk_listen = *talker_ad;
2485         msrp_event(MRP_EVENT_JOIN, attrib);
2486
2487         return 0;
2488 }
2489
2490 /* S-L   Withdraw a listener status */
2491 int msrp_cmd_parse_withdraw_listener_status(
2492                 char *buf, int buflen,
2493                 struct msrpdu_talker_fail *talker_ad,
2494                 int *err_index
2495 )
2496 {
2497         struct parse_param specs[] = {
2498                 {"L" PARSE_ASSIGN, parse_c64, talker_ad->StreamID},
2499                 {0, parse_null, 0}
2500         };
2501         if (buflen < 22)
2502                 return -1;
2503
2504         memset(talker_ad, 0, sizeof(*talker_ad));
2505         return parse(buf + 4, buflen - 4, specs, err_index);
2506 }
2507
2508 int msrp_cmd_withdraw_listener_status(
2509                 struct msrpdu_talker_fail *talker_ad
2510 )
2511 {
2512         struct msrp_attribute *attrib;
2513
2514         attrib = msrp_alloc();
2515         if (NULL == attrib) {
2516                 return -1;
2517         }
2518         attrib->type = MSRP_LISTENER_TYPE;
2519         attrib->attribute.talk_listen = *talker_ad;
2520         msrp_event(MRP_EVENT_LV, attrib);
2521
2522         return 0;
2523 }
2524
2525
2526 /* S+D   Report a domain status */
2527 /* S-D   Withdraw a domain status */
2528 int msrp_cmd_parse_domain_status(
2529                 char *buf, int buflen,
2530                 struct msrpdu_domain *domain,
2531                 int *err_index
2532 )
2533 {
2534         struct parse_param specs[] = {
2535                 {"C" PARSE_ASSIGN, parse_u8, &domain->SRclassID},
2536                 {"P" PARSE_ASSIGN, parse_u8, &domain->SRclassPriority},
2537                 {"V" PARSE_ASSIGN, parse_u16_04x, &domain->SRclassVID},
2538                 {0, parse_null, 0}
2539         };
2540         if (buflen < 18)
2541                 return -1;
2542         memset(domain, 0, sizeof(*domain));
2543         return parse(buf + 4, buflen - 4, specs, err_index);
2544 }
2545
2546 int msrp_cmd_report_domain_status(
2547                 struct msrpdu_domain *domain,
2548                 int report)
2549 {
2550         struct msrp_attribute *attrib;
2551
2552         attrib = msrp_alloc();
2553         if (NULL == attrib) {
2554                 return -1;
2555         }
2556         attrib->attribute.domain = *domain;
2557         if (report)
2558                 msrp_event(MRP_EVENT_JOIN, attrib);
2559         else
2560                 msrp_event(MRP_EVENT_LV, attrib);
2561
2562         return 0;
2563 }
2564
2565 int msrp_recv_cmd(char *buf, int buflen, struct sockaddr_in *client)
2566 {
2567         int rc;
2568         char respbuf[8];
2569         int join;
2570         unsigned int substate;
2571         struct msrpdu_domain domain_param;
2572         struct msrpdu_talker_fail talker_param;
2573         int err_index;
2574
2575         if (NULL == MSRP_db) {
2576                 snprintf(respbuf, sizeof(respbuf) - 1, "ERC %s", buf);
2577                 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
2578                 goto out;
2579         }
2580
2581         rc = mrp_client_add(&(MSRP_db->mrp_db.clients), client);
2582
2583         if (buflen < 3)
2584                 return -1;
2585
2586         if ('S' != buf[0])
2587                 return -1;
2588
2589         /*
2590          * S?? - query MSRP Registrar database
2591          * S+? - (re)JOIN a stream
2592          * S++   NEW a stream
2593          * S-- - LV a stream
2594          * S+L   Report a listener status
2595          * S-L   Withdraw a listener status
2596          * S+D   Report a domain status
2597          * S-D   Withdraw a domain status
2598          */
2599
2600
2601         if (strncmp(buf, "S??", 3)==0) {
2602                 msrp_dumptable(client);
2603
2604         } else if (strncmp(buf, "S-L", 3) == 0) {
2605
2606                 /* buf[] should look similar to 'S-L:L=xxyyzz...' */
2607                 rc = msrp_cmd_parse_withdraw_listener_status(buf, buflen, &talker_param, &err_index);
2608                 if (rc)
2609                         goto out_ERP;
2610                 rc = msrp_cmd_withdraw_listener_status(&talker_param);
2611                 if (rc)
2612                         goto out_ERI;   /* oops - internal error */
2613         } else if (strncmp(buf, "S-D", 3) == 0) {
2614
2615                 /* buf[] should look similar to 'S-D:C=%d,P=%d,V:%04x" */
2616                 rc = msrp_cmd_parse_domain_status(buf, buflen, &domain_param, &err_index);
2617                 if (rc)
2618                         goto out_ERP;
2619                 rc = msrp_cmd_report_domain_status(&domain_param, 0);
2620                 if (rc)
2621                         goto out_ERI;   /* oops - internal error */
2622         } else if (strncmp(buf, "S--", 3) == 0) {
2623                 /* buf[] should look similar to 'S--:S=xxyyzz...' */
2624                 rc = msrp_cmd_parse_leave_stream(buf, buflen, &talker_param, &err_index);
2625                 if (rc)
2626                         goto out_ERP;
2627                 rc = msrp_cmd_leave_stream(&talker_param);
2628                 if (rc)
2629                         goto out_ERI;   /* oops - internal error */
2630         } else if (strncmp(buf, "S+L", 3) == 0) {
2631                 /* buf[] should look similar to 'S+L:L=xxyyzz...:D=a' */
2632                 rc = msrp_cmd_parse_report_listener_status(buf, buflen, &talker_param, &substate, &err_index);
2633                 if (rc)
2634                         goto out_ERP;
2635                 rc = msrp_cmd_report_listener_status(&talker_param, substate);
2636                 if (rc)
2637                         goto out_ERI;   /* oops - internal error */
2638         } else if (strncmp(buf, "S+D", 3) == 0) {
2639                 /* buf[] should look similar to 'S+D:C=%d,P=%d,V=%04x" */
2640                 rc = msrp_cmd_parse_domain_status(buf, buflen, &domain_param, &err_index);
2641                 if (rc)
2642                         goto out_ERP;
2643                 rc = msrp_cmd_report_domain_status(&domain_param, 1);
2644                 if (rc)
2645                         goto out_ERI;   /* oops - internal error */
2646         } else if ((strncmp(buf, "S+?", 3) == 0) || (strncmp(buf, "S++", 3) == 0) ){
2647                 join = (buf[2] == '?');
2648                 /*
2649                  * create or join a stream
2650                  * interesting to note the spec doesn't talk about
2651                  * what happens if two talkers attempt to define the identical
2652                  * stream twice  - does the bridge report STREAM_CHANGE error?
2653                  */
2654
2655                 /*
2656                    buf[] should look similar to "S=%02x%02x%02x%02x%02x%02x%02x%02x"
2657                    ",A=%02x%02x%02x%02x%02x%02x"
2658                    ",V=%04x" \
2659                    ",Z=%d" \
2660                    ",I=%d" \
2661                    ",P=%d" \
2662                    ",L=%d" \
2663                  */
2664                 rc = msrp_cmd_parse_join_or_new_stream(buf, buflen, &talker_param, &err_index);
2665                 if (rc)
2666                         goto out_ERP;
2667                 rc = msrp_cmd_join_or_new_stream(join, &talker_param);
2668                 if (rc)
2669                         goto out_ERI;   /* oops - internal error */
2670         } else {
2671                 snprintf(respbuf, sizeof(respbuf) - 1, "ERC %s", buf);
2672                 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
2673                 goto out;
2674         }
2675         return 0;
2676
2677 out_ERI:
2678         snprintf(respbuf, sizeof(respbuf) - 1, "ERI %s", buf);
2679         mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
2680         goto out;
2681
2682 out_ERP:
2683         snprintf(respbuf, sizeof(respbuf) - 1, "ERP %s", buf);
2684         mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
2685         goto out;
2686
2687  out:
2688         return -1;
2689 }
2690
2691 int msrp_init(int msrp_enable)
2692 {
2693         int rc;
2694
2695         /* XXX doesn't handle re-start */
2696
2697         msrp_socket = INVALID_SOCKET;
2698         MSRP_db = NULL;
2699
2700         if (0 == msrp_enable) {
2701                 return 0;
2702         }
2703
2704         rc = mrpd_init_protocol_socket(MSRP_ETYPE, &msrp_socket, MSRP_ADDR);
2705         if (rc < 0)
2706                 return -1;
2707
2708         MSRP_db = malloc(sizeof(struct msrp_database));
2709
2710         if (NULL == MSRP_db)
2711                 goto abort_socket;
2712
2713         memset(MSRP_db, 0, sizeof(struct msrp_database));
2714
2715         /* if registration is FIXED or FORBIDDEN
2716          * updates from MRP are discarded, and
2717          * only IN and JOININ messages are sent
2718          */
2719         MSRP_db->mrp_db.registration = MRP_REGISTRAR_CTL_NORMAL;        /* default */
2720
2721         /* if participant role is 'SILENT' (or non-participant)
2722          * applicant doesn't send any messages -
2723          *
2724          * Note - theoretically configured per-attribute
2725          */
2726         MSRP_db->mrp_db.participant = MRP_APPLICANT_CTL_NORMAL; /* default */
2727
2728         rc = mrpd_init_timers(&(MSRP_db->mrp_db));
2729
2730         if (rc < 0)
2731                 goto abort_alloc;
2732
2733         mrp_lvatimer_fsm(&(MSRP_db->mrp_db), MRP_EVENT_BEGIN);
2734
2735         return 0;
2736
2737  abort_alloc:
2738         /* free MSRP_db and related structures */
2739         free(MSRP_db);
2740         MSRP_db = NULL;
2741  abort_socket:
2742         mrpd_close_socket(msrp_socket);
2743         msrp_socket = INVALID_SOCKET;
2744         /* XXX */
2745         return -1;
2746 }
2747
2748 void msrp_bye(struct sockaddr_in *client)
2749 {
2750         if (NULL != MSRP_db)
2751                 mrp_client_delete(&(MSRP_db->mrp_db.clients), client);
2752 }
2753
2754 int msrp_reclaim(void)
2755 {
2756         struct msrp_attribute *sattrib, *free_sattrib;
2757
2758         if (NULL == MSRP_db)
2759                 return 0;
2760
2761         sattrib = MSRP_db->attrib_list;
2762         while (NULL != sattrib) {
2763                 if ((sattrib->registrar.mrp_state == MRP_MT_STATE) &&
2764                     ((sattrib->applicant.mrp_state == MRP_VO_STATE) ||
2765                      (sattrib->applicant.mrp_state == MRP_AO_STATE) ||
2766                      (sattrib->applicant.mrp_state == MRP_QO_STATE))) {
2767                         if (NULL != sattrib->prev)
2768                                 sattrib->prev->next = sattrib->next;
2769                         else
2770                                 MSRP_db->attrib_list = sattrib->next;
2771                         if (NULL != sattrib->next)
2772                                 sattrib->next->prev = sattrib->prev;
2773                         free_sattrib = sattrib;
2774                         sattrib = sattrib->next;
2775                         msrp_send_notifications(free_sattrib, MRP_NOTIFY_LV);
2776                         free(free_sattrib);
2777                 } else
2778                         sattrib = sattrib->next;
2779         }
2780         return 0;
2781 }