gen.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. // Copyright 2013 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // +build ignore
  5. //go:generate go run gen.go
  6. // This program generates internet protocol constants and tables by
  7. // reading IANA protocol registries.
  8. package main
  9. import (
  10. "bytes"
  11. "encoding/xml"
  12. "fmt"
  13. "go/format"
  14. "io"
  15. "io/ioutil"
  16. "net/http"
  17. "os"
  18. "strconv"
  19. "strings"
  20. )
  21. var registries = []struct {
  22. url string
  23. parse func(io.Writer, io.Reader) error
  24. }{
  25. {
  26. "http://www.iana.org/assignments/dscp-registry/dscp-registry.xml",
  27. parseDSCPRegistry,
  28. },
  29. {
  30. "http://www.iana.org/assignments/ipv4-tos-byte/ipv4-tos-byte.xml",
  31. parseTOSTCByte,
  32. },
  33. {
  34. "http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml",
  35. parseProtocolNumbers,
  36. },
  37. }
  38. func main() {
  39. var bb bytes.Buffer
  40. fmt.Fprintf(&bb, "// go generate gen.go\n")
  41. fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n")
  42. fmt.Fprintf(&bb, "// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).\n")
  43. fmt.Fprintf(&bb, `package iana // import "golang.org/x/net/internal/iana"`+"\n\n")
  44. for _, r := range registries {
  45. resp, err := http.Get(r.url)
  46. if err != nil {
  47. fmt.Fprintln(os.Stderr, err)
  48. os.Exit(1)
  49. }
  50. defer resp.Body.Close()
  51. if resp.StatusCode != http.StatusOK {
  52. fmt.Fprintf(os.Stderr, "got HTTP status code %v for %v\n", resp.StatusCode, r.url)
  53. os.Exit(1)
  54. }
  55. if err := r.parse(&bb, resp.Body); err != nil {
  56. fmt.Fprintln(os.Stderr, err)
  57. os.Exit(1)
  58. }
  59. fmt.Fprintf(&bb, "\n")
  60. }
  61. b, err := format.Source(bb.Bytes())
  62. if err != nil {
  63. fmt.Fprintln(os.Stderr, err)
  64. os.Exit(1)
  65. }
  66. if err := ioutil.WriteFile("const.go", b, 0644); err != nil {
  67. fmt.Fprintln(os.Stderr, err)
  68. os.Exit(1)
  69. }
  70. }
  71. func parseDSCPRegistry(w io.Writer, r io.Reader) error {
  72. dec := xml.NewDecoder(r)
  73. var dr dscpRegistry
  74. if err := dec.Decode(&dr); err != nil {
  75. return err
  76. }
  77. drs := dr.escape()
  78. fmt.Fprintf(w, "// %s, Updated: %s\n", dr.Title, dr.Updated)
  79. fmt.Fprintf(w, "const (\n")
  80. for _, dr := range drs {
  81. fmt.Fprintf(w, "DiffServ%s = %#x", dr.Name, dr.Value)
  82. fmt.Fprintf(w, "// %s\n", dr.OrigName)
  83. }
  84. fmt.Fprintf(w, ")\n")
  85. return nil
  86. }
  87. type dscpRegistry struct {
  88. XMLName xml.Name `xml:"registry"`
  89. Title string `xml:"title"`
  90. Updated string `xml:"updated"`
  91. Note string `xml:"note"`
  92. RegTitle string `xml:"registry>title"`
  93. PoolRecords []struct {
  94. Name string `xml:"name"`
  95. Space string `xml:"space"`
  96. } `xml:"registry>record"`
  97. Records []struct {
  98. Name string `xml:"name"`
  99. Space string `xml:"space"`
  100. } `xml:"registry>registry>record"`
  101. }
  102. type canonDSCPRecord struct {
  103. OrigName string
  104. Name string
  105. Value int
  106. }
  107. func (drr *dscpRegistry) escape() []canonDSCPRecord {
  108. drs := make([]canonDSCPRecord, len(drr.Records))
  109. sr := strings.NewReplacer(
  110. "+", "",
  111. "-", "",
  112. "/", "",
  113. ".", "",
  114. " ", "",
  115. )
  116. for i, dr := range drr.Records {
  117. s := strings.TrimSpace(dr.Name)
  118. drs[i].OrigName = s
  119. drs[i].Name = sr.Replace(s)
  120. n, err := strconv.ParseUint(dr.Space, 2, 8)
  121. if err != nil {
  122. continue
  123. }
  124. drs[i].Value = int(n) << 2
  125. }
  126. return drs
  127. }
  128. func parseTOSTCByte(w io.Writer, r io.Reader) error {
  129. dec := xml.NewDecoder(r)
  130. var ttb tosTCByte
  131. if err := dec.Decode(&ttb); err != nil {
  132. return err
  133. }
  134. trs := ttb.escape()
  135. fmt.Fprintf(w, "// %s, Updated: %s\n", ttb.Title, ttb.Updated)
  136. fmt.Fprintf(w, "const (\n")
  137. for _, tr := range trs {
  138. fmt.Fprintf(w, "%s = %#x", tr.Keyword, tr.Value)
  139. fmt.Fprintf(w, "// %s\n", tr.OrigKeyword)
  140. }
  141. fmt.Fprintf(w, ")\n")
  142. return nil
  143. }
  144. type tosTCByte struct {
  145. XMLName xml.Name `xml:"registry"`
  146. Title string `xml:"title"`
  147. Updated string `xml:"updated"`
  148. Note string `xml:"note"`
  149. RegTitle string `xml:"registry>title"`
  150. Records []struct {
  151. Binary string `xml:"binary"`
  152. Keyword string `xml:"keyword"`
  153. } `xml:"registry>record"`
  154. }
  155. type canonTOSTCByteRecord struct {
  156. OrigKeyword string
  157. Keyword string
  158. Value int
  159. }
  160. func (ttb *tosTCByte) escape() []canonTOSTCByteRecord {
  161. trs := make([]canonTOSTCByteRecord, len(ttb.Records))
  162. sr := strings.NewReplacer(
  163. "Capable", "",
  164. "(", "",
  165. ")", "",
  166. "+", "",
  167. "-", "",
  168. "/", "",
  169. ".", "",
  170. " ", "",
  171. )
  172. for i, tr := range ttb.Records {
  173. s := strings.TrimSpace(tr.Keyword)
  174. trs[i].OrigKeyword = s
  175. ss := strings.Split(s, " ")
  176. if len(ss) > 1 {
  177. trs[i].Keyword = strings.Join(ss[1:], " ")
  178. } else {
  179. trs[i].Keyword = ss[0]
  180. }
  181. trs[i].Keyword = sr.Replace(trs[i].Keyword)
  182. n, err := strconv.ParseUint(tr.Binary, 2, 8)
  183. if err != nil {
  184. continue
  185. }
  186. trs[i].Value = int(n)
  187. }
  188. return trs
  189. }
  190. func parseProtocolNumbers(w io.Writer, r io.Reader) error {
  191. dec := xml.NewDecoder(r)
  192. var pn protocolNumbers
  193. if err := dec.Decode(&pn); err != nil {
  194. return err
  195. }
  196. prs := pn.escape()
  197. prs = append([]canonProtocolRecord{{
  198. Name: "IP",
  199. Descr: "IPv4 encapsulation, pseudo protocol number",
  200. Value: 0,
  201. }}, prs...)
  202. fmt.Fprintf(w, "// %s, Updated: %s\n", pn.Title, pn.Updated)
  203. fmt.Fprintf(w, "const (\n")
  204. for _, pr := range prs {
  205. if pr.Name == "" {
  206. continue
  207. }
  208. fmt.Fprintf(w, "Protocol%s = %d", pr.Name, pr.Value)
  209. s := pr.Descr
  210. if s == "" {
  211. s = pr.OrigName
  212. }
  213. fmt.Fprintf(w, "// %s\n", s)
  214. }
  215. fmt.Fprintf(w, ")\n")
  216. return nil
  217. }
  218. type protocolNumbers struct {
  219. XMLName xml.Name `xml:"registry"`
  220. Title string `xml:"title"`
  221. Updated string `xml:"updated"`
  222. RegTitle string `xml:"registry>title"`
  223. Note string `xml:"registry>note"`
  224. Records []struct {
  225. Value string `xml:"value"`
  226. Name string `xml:"name"`
  227. Descr string `xml:"description"`
  228. } `xml:"registry>record"`
  229. }
  230. type canonProtocolRecord struct {
  231. OrigName string
  232. Name string
  233. Descr string
  234. Value int
  235. }
  236. func (pn *protocolNumbers) escape() []canonProtocolRecord {
  237. prs := make([]canonProtocolRecord, len(pn.Records))
  238. sr := strings.NewReplacer(
  239. "-in-", "in",
  240. "-within-", "within",
  241. "-over-", "over",
  242. "+", "P",
  243. "-", "",
  244. "/", "",
  245. ".", "",
  246. " ", "",
  247. )
  248. for i, pr := range pn.Records {
  249. if strings.Contains(pr.Name, "Deprecated") ||
  250. strings.Contains(pr.Name, "deprecated") {
  251. continue
  252. }
  253. prs[i].OrigName = pr.Name
  254. s := strings.TrimSpace(pr.Name)
  255. switch pr.Name {
  256. case "ISIS over IPv4":
  257. prs[i].Name = "ISIS"
  258. case "manet":
  259. prs[i].Name = "MANET"
  260. default:
  261. prs[i].Name = sr.Replace(s)
  262. }
  263. ss := strings.Split(pr.Descr, "\n")
  264. for i := range ss {
  265. ss[i] = strings.TrimSpace(ss[i])
  266. }
  267. if len(ss) > 1 {
  268. prs[i].Descr = strings.Join(ss, " ")
  269. } else {
  270. prs[i].Descr = ss[0]
  271. }
  272. prs[i].Value, _ = strconv.Atoi(pr.Value)
  273. }
  274. return prs
  275. }