@@ -16,6 +16,9 @@ import (
16
16
"fmt"
17
17
"io"
18
18
"math"
19
+ "os"
20
+ "path"
21
+ "runtime"
19
22
"time"
20
23
)
21
24
@@ -219,6 +222,7 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error {
219
222
clientTransactions |
220
223
clientLocalFiles |
221
224
clientPluginAuth |
225
+ clientConnectAttrs |
222
226
mc .flags & clientLongFlag
223
227
224
228
if mc .cfg .clientFoundRows {
@@ -233,7 +237,23 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error {
233
237
// User Password
234
238
scrambleBuff := scramblePassword (cipher , []byte (mc .cfg .passwd ))
235
239
240
+ attrs := map [string ]string {
241
+ "_os" : runtime .GOOS ,
242
+ "_client_name" : "Go-MySQL-Driver" ,
243
+ "_pid" : pid ,
244
+ "_platform" : runtime .GOARCH ,
245
+ "program_name" : path .Base (os .Args [0 ]),
246
+ }
247
+
248
+ attrlen := 0
249
+ for attrname , attrvalue := range attrs {
250
+ attrlen += len (attrname ) + len (attrvalue )
251
+ // one byte to store attrname length and one byte to store attrvalue length
252
+ attrlen += 2
253
+ }
254
+
236
255
pktLen := 4 + 4 + 1 + 23 + len (mc .cfg .user ) + 1 + 1 + len (scrambleBuff ) + 21 + 1
256
+ pktLen += attrlen + 1 // one byte to store the total length of attrs
237
257
238
258
// To specify a db name
239
259
if n := len (mc .cfg .dbname ); n > 0 {
@@ -305,6 +325,19 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error {
305
325
// Assume native client during response
306
326
pos += copy (data [pos :], "mysql_native_password" )
307
327
data [pos ] = 0x00
328
+ pos ++
329
+
330
+ // Connection attributes
331
+ data [pos ] = byte (attrlen )
332
+ pos ++
333
+
334
+ for attrname , attrvalue := range attrs {
335
+ data [pos ] = byte (len (attrname ))
336
+ pos += 1 + copy (data [pos + 1 :], attrname )
337
+
338
+ data [pos ] = byte (len (attrvalue ))
339
+ pos += 1 + copy (data [pos + 1 :], attrvalue )
340
+ }
308
341
309
342
// Send Auth packet
310
343
return mc .writePacket (data )
0 commit comments